<?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>17510</bug_id>
          
          <creation_ts>2008-02-24 01:40:34 -0800</creation_ts>
          <short_desc>Acid3 test 26 takes &gt;33ms</short_desc>
          <delta_ts>2008-06-06 14:51:27 -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>JavaScriptCore</component>
          <version>528+ (Nightly build)</version>
          <rep_platform>Mac</rep_platform>
          <op_sys>OS X 10.5</op_sys>
          <bug_status>RESOLVED</bug_status>
          <resolution>FIXED</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>
          <dependson>19239</dependson>
          <blocked>17064</blocked>
          <everconfirmed>1</everconfirmed>
          <reporter name="Darin Adler">darin</reporter>
          <assigned_to name="Nobody">webkit-unassigned</assigned_to>
          <cc>ap</cc>
    
    <cc>ian</cc>
    
    <cc>mjs</cc>
    
    <cc>mrowe</cc>
    
    <cc>puurtuur</cc>
    
    <cc>sam</cc>
    
    <cc>webmaster</cc>
    
    <cc>wjmoore</cc>
          

      

      

      

          <comment_sort_order>oldest_to_newest</comment_sort_order>  
          <long_desc isprivate="0" >
    <commentid>71708</commentid>
    <comment_count>0</comment_count>
    <who name="Darin Adler">darin</who>
    <bug_when>2008-02-24 01:40:34 -0800</bug_when>
    <thetext>While running test 26, Acid3 pauses. That&apos;s because the test forces garbage collection as a sort of mini performance test. I don&apos;t know how fixable this is, but even on my fast computer with a Release build the pause is noticeable. The problem is that the faster we run the other tests, the more even a slight pause is noticeable, so I&apos;m not sure this is practical to fix.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>72785</commentid>
    <comment_count>1</comment_count>
    <who name="Maciej Stachowiak">mjs</who>
    <bug_when>2008-03-05 00:08:49 -0800</bug_when>
    <thetext>Reopening, I closed this by mistake.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>72786</commentid>
    <comment_count>2</comment_count>
    <who name="Maciej Stachowiak">mjs</who>
    <bug_when>2008-03-05 00:11:42 -0800</bug_when>
    <thetext>Some testing with a local copy shows that we&apos;d have to speed up performance on the loop part of test 26 by 3-4x to avoid pausing noticeably. I&apos;m not sure how practical this is.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>72801</commentid>
    <comment_count>3</comment_count>
    <who name="Darin Adler">darin</who>
    <bug_when>2008-03-05 08:28:47 -0800</bug_when>
    <thetext>3-4x will be a serious challenge given how much faster we are already. I&apos;d like to know what kind of loop it is and if it&apos;s pure JavaScript or involves DOM.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>72829</commentid>
    <comment_count>4</comment_count>
    <who name="vasi">djvasi</who>
    <bug_when>2008-03-05 12:18:58 -0800</bug_when>
    <thetext>The loop does indeed involve the DOM. Here&apos;s the JS, for ease of reference:

      var loops = ((new Date().valueOf() - 1.1e12) / 32e9) * 0x500; // increases linearly over time
      for (var i = 0; i &lt; loops; i += 1) {
        // we want to force a GC here, so we use up lots of memory
        // we take the opportunity to sneak in a perf test to make DOM and JS stuff faster...
        d = new Date();
        d = new (function (x) { return { toString: function () { return x.toString() } } })(d.valueOf());
        d = document.createTextNode(&quot;iteration &quot; + i + &quot; at &quot; + d);
        document.createElement(&apos;a&apos;).appendChild(d);
        d = d.parentNode;
        document.body.insertBefore(d, document.getElementById(&apos;bucket1&apos;).parentNode);
        assert(document.getElementById(&apos;bucket2&apos;).nextSibling.parentNode.previousSibling.firstChild.data.match(/AT\W/i), &quot;iteration &quot; + i + &quot; failed&quot;);
        d.setAttribute(&apos;class&apos;, d.textContent);
        document.body.removeChild(d);
      }

</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>72830</commentid>
    <comment_count>5</comment_count>
    <who name="Ian &apos;Hixie&apos; Hickson">ian</who>
    <bug_when>2008-03-05 12:53:44 -0800</bug_when>
    <thetext>What comes up on a profile of that loop?</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>74021</commentid>
    <comment_count>6</comment_count>
      <attachid>19820</attachid>
    <who name="Maciej Stachowiak">mjs</who>
    <bug_when>2008-03-16 19:54:56 -0700</bug_when>
    <thetext>Created attachment 19820
Standalone version of test 26, for profiling goodness</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>74158</commentid>
    <comment_count>7</comment_count>
    <who name="Darin Adler">darin</who>
    <bug_when>2008-03-17 14:28:07 -0700</bug_when>
    <thetext>I started looking at the profile. There&apos;s no one huge item here--a lot of stuff is pretty fundamental--but there are various things we could improve. One recurring area seems to be conversions from numbers to strings and from WebCore strings to JavaScriptCore strings.

In this profile:

    - The top item on the list is 4.3% in KJS::Lookup::findEntry; the hash tables we use to look up built-in properties are not working well enough; some kind of single element cache might save the day, or we could come up with a more efficient technique for this.

    - We are spending 2.7% of the time in UString::from(double), converting the loop count into a string so it can be appended to another string to create a text node.

    - We are spending 2.3% of the time in StringImpl::create, allocating new WebCore::String objects. If you include ~StringImpl (and we should), then it&apos;s 3.4%. Most of this time, 1.8%, is in JSHTMLDocument::canGetItemsForName. We should change this code path so it doesn&apos;t involve allocating a String. But also 0.2% for setAttribute and 0.2% for getElementById and 0.1% for createTextNode.

    - 1.2% of the time is in Document::isValidName. We&apos;ve got to be able to do that one faster!

    - 1.1% of the time is in JSHTMLDocument::canGetItemsForName, not counting the string creation. We&apos;ve got to be able to do that one faster!

    - 1.1% of the time is spent in getDOMNodeForDocument, finding wrappers for the DOM nodes. Two hash table lookups every time. Maybe we should abandon the purity of it and put wrapper pointers into DOM::Node?

    - 1.1% of the time is in the GC allocator.

    - 1.1% of the time is in parseClassAttribute, which has to fold case and break up an arbitrary string into a list of class names. Maybe we could defer that parsing until style resolution time? Or add a fast case for when all the letters are non-upper-case ASCII.

    - 0.9% of the time is spent changing a char* into an AtomicString in JHTMLAnchorElementPrototype::self and JSTextPrototoype::self. Seems fixable.

    - 0.8% of the time is spent concatenating UString objects; because of the createTextNode and the assert in this function, it&apos;s a stress test of string appending.

    - We are spending 0.7% of our time in Document::isValidName checking the string &quot;class&quot; to see if it&apos;s a valid name, in an expensive ICU u_getIntPropertyValue call.

    - 0.7% is spent just in JSObject::type.

    - 0.5% of the time is spent changing an ID into an AtomicString in getElementById. And an additional 0.3% each is spent in setAttribute and createElement doing the same thing. Since these are the same short ASCII strings over and over again we should think about how to do it faster.

    - 0.3% of the time is converting a DOM string to a JavaScript string in JSCharacterData::getValueProperty; presumably this is the &quot;.data&quot; call in the assert.

There&apos;s also some more of the pure JavaScript interpreter overhead, looking up properties and such.

It&apos;s costing us performance that all calls to toJS are going through EventTarget* first and only then going on to Node*. We need to change the Node* one from PassRefPtr to Node* and then eliminate all the ambiguity. We want calls to all go straight to the Node* version!</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>74186</commentid>
    <comment_count>8</comment_count>
    <who name="Ian &apos;Hixie&apos; Hickson">ian</who>
    <bug_when>2008-03-17 16:24:50 -0700</bug_when>
    <thetext>Woot, now we&apos;re talking. That&apos;s the kind of scrutiny I was hoping this subtest would bring to the table! :-)</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>74215</commentid>
    <comment_count>9</comment_count>
      <attachid>19858</attachid>
    <who name="Darin Adler">darin</who>
    <bug_when>2008-03-17 21:41:58 -0700</bug_when>
    <thetext>Created attachment 19858
alternate version, larger, non-variable loop count so easier to profile</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>74216</commentid>
    <comment_count>10</comment_count>
    <who name="Darin Adler">darin</who>
    <bug_when>2008-03-17 21:42:38 -0700</bug_when>
    <thetext>(In reply to comment #8)
&gt; Woot, now we&apos;re talking. That&apos;s the kind of scrutiny I was hoping this subtest
&gt; would bring to the table! :-)

I&apos;m sure we&apos;ll be able to get a lot faster, but I still think 3x may be impossible.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>75408</commentid>
    <comment_count>11</comment_count>
    <who name="Darin Adler">darin</who>
    <bug_when>2008-03-26 21:32:52 -0700</bug_when>
    <thetext>I don&apos;t see a pause at all on my Mac Pro now (in Release builds). So on faster machines this is resolved. Maciej was thinking of setting a target for how much faster we need to get it.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>75412</commentid>
    <comment_count>12</comment_count>
    <who name="Maciej Stachowiak">mjs</who>
    <bug_when>2008-03-26 22:26:24 -0700</bug_when>
    <thetext>I get around 75 milliseconds on my MacBook Pro, but I do not see a visible pause. I would like to hear what the Acid3 editor thinks of the animation smoothness in a recent release build.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>75423</commentid>
    <comment_count>13</comment_count>
    <who name="Ian &apos;Hixie&apos; Hickson">ian</who>
    <bug_when>2008-03-26 23:51:32 -0700</bug_when>
    <thetext>I got about 87ms. I definitely saw a noticeable skip during the second box.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>75474</commentid>
    <comment_count>14</comment_count>
    <who name="Darin Adler">darin</who>
    <bug_when>2008-03-27 10:10:07 -0700</bug_when>
    <thetext>Hixie&apos;s put a 33ms target into the test. Retitling this bug appropriately.

On my Mac Pro, we&apos;re currently at about 60ms, so it seems we still need to double our speed on this to make the target on this fast computer.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>75494</commentid>
    <comment_count>15</comment_count>
    <who name="Brady Eidson">beidson</who>
    <bug_when>2008-03-27 11:44:49 -0700</bug_when>
    <thetext>Has there been any stance about the performance aspect of this test relying on the hardware its run on?

Say we almost double the performance so Darin&apos;s Mac Pro squeaks by at 32ms.  WebKit is still supported on some pretty old sub-ghz PPC machines, and test 26 would certainly be slower than 33ms there.
</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>75507</commentid>
    <comment_count>16</comment_count>
    <who name="Ian &apos;Hixie&apos; Hickson">ian</who>
    <bug_when>2008-03-27 13:37:36 -0700</bug_when>
    <thetext>I wouldn&apos;t focus so much on the pass/fail aspect of this. The idea is to improve performance to the best possible. Darin pointed out a number of things that could be done to improve perf, and many of them would help across many pages, which is what matters.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>75508</commentid>
    <comment_count>17</comment_count>
    <who name="Ian &apos;Hixie&apos; Hickson">ian</who>
    <bug_when>2008-03-27 13:39:35 -0700</bug_when>
    <thetext>BTW, it&apos;s psychologically hard to see how WebKit could make things faster, because it&apos;s the fastest. Obviously another browser can see that it is possible to go faster, since WebKit does so. What would you do if one of the other browsers managed to squeeze a few more milliseconds out and beat WebKit?</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>75577</commentid>
    <comment_count>18</comment_count>
    <who name="Darin Adler">darin</who>
    <bug_when>2008-03-27 21:57:28 -0700</bug_when>
    <thetext>(In reply to comment #16)
&gt; I wouldn&apos;t focus so much on the pass/fail aspect of this. The idea is to
&gt; improve performance to the best possible. Darin pointed out a number of things
&gt; that could be done to improve perf, and many of them would help across many
&gt; pages, which is what matters.

Yes, and I&apos;ve addressed almost all those things I listed already. It&apos;s a long road of small separate performance increases. A target is, in fact, (in my experience) very important for a project like this.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>75582</commentid>
    <comment_count>19</comment_count>
    <who name="Ian &apos;Hixie&apos; Hickson">ian</who>
    <bug_when>2008-03-27 22:09:56 -0700</bug_when>
    <thetext>Ok. um, 33ms on the state of the art Apple laptop hardware, I guess. I&apos;m just saying that I wouldn&apos;t prioritise this above correctness bugs. The goal is arbitrary. So long as WebKit is faster than everything else, it&apos;s hard to give a convincing reason why it should be faster.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>75594</commentid>
    <comment_count>20</comment_count>
    <who name="Arthur Langereis">puurtuur</who>
    <bug_when>2008-03-28 00:43:02 -0700</bug_when>
    <thetext>I can give a reason why it should be faster: iPhone web development. The iPhone is probably the slowest device running WebKit on the market right now and anything, _anything_ that increases JS execution speed on it will help.

Don&apos;t get me wrong, I love all the progress done here and WK really _is_ the fastest kid on the block right now, but the iPhone is both very popular and very slow (relatively speaking.) Speeding up commonly used code by a factor of 1.5x to 2x by using common sense and overhead elimination is never a bad thing in my book.

And even beside the iPhone, I really wouldn&apos;t mind more JS speed any day on any machine. JS code has about a 1000x performance hit compared to native code and any and all efforts to narrow that gap will be much appreciated by anyone doing advanced client side programming.

Sorry for the rant, I hope my arguments are valid. Thanks for all the effort.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>75624</commentid>
    <comment_count>21</comment_count>
    <who name="Arthur Langereis">puurtuur</who>
    <bug_when>2008-03-28 03:51:36 -0700</bug_when>
    <thetext>Sorry for the spam, but before I get lynched I&apos;d like to correct my 1000x speed hit statement. This may have been true as of Safari 1, but currently the speed hit seems to be around 50x (pure language wise.) I tested this by comparing a native C implementation of my bits-in-byte tests to the JS versions that have been incorporated in Sunspider. Also, my JS implementation of my NES emulator can now emulate up to 30 frames of CPU activity (no audio or graphics) per second which is really quite respectable.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>75712</commentid>
    <comment_count>22</comment_count>
    <who name="Maciej Stachowiak">mjs</who>
    <bug_when>2008-03-28 17:35:56 -0700</bug_when>
    <thetext>Improving JS execution speed for the iPhone is certainly something we plan to do. I am not sure this benchmark is the best metric to drive that though. Getting faster on this test would be all about Acid3.

Now that Opera has posted a build that otherwise passes Acid3, we can see that we are about 5x faster than them on this test on reasonable laptop hardware.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>75713</commentid>
    <comment_count>23</comment_count>
    <who name="Darin Adler">darin</who>
    <bug_when>2008-03-28 17:37:28 -0700</bug_when>
    <thetext>(In reply to comment #22)
&gt; Now that Opera has posted a build that otherwise passes Acid3, we can see that
&gt; we are about 5x faster than them on this test on reasonable laptop hardware.

Not that it&apos;s important, but what I saw was 3.5x, not 5x.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>80629</commentid>
    <comment_count>24</comment_count>
    <who name="Waleof Suous">dark0eternal</who>
    <bug_when>2008-05-16 08:40:10 -0700</bug_when>
    <thetext>(In reply to comment #22)
&gt; Improving JS execution speed for the iPhone is certainly something we plan to
&gt; do. I am not sure this benchmark is the best metric to drive that though.
&gt; Getting faster on this test would be all about Acid3.
&gt; 
&gt; Now that Opera has posted a build that otherwise passes Acid3, we can see that
&gt; we are about 5x faster than them on this test on reasonable laptop hardware.
&gt; 

WebKit is faster than Opera in the two &quot;failed&quot; tests, but Opera is faster than WebKit in the overall speed. When they first released, WebKit takes more than 4 seconds total to finish the test 100/100, while Opera takes around 1 second total to finish the test 100/100</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>81376</commentid>
    <comment_count>25</comment_count>
      <attachid>21325</attachid>
    <who name="Maciej Stachowiak">mjs</who>
    <bug_when>2008-05-23 20:25:31 -0700</bug_when>
    <thetext>Created attachment 21325
better version of Darin&apos;s extended version

New version of the test content for profiling. Properly puts the test in function scope.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>81380</commentid>
    <comment_count>26</comment_count>
    <who name="Maciej Stachowiak">mjs</who>
    <bug_when>2008-05-23 21:17:18 -0700</bug_when>
    <thetext>Some optimization ideas:

1) stringProtoFuncMatch spends 3.4% of its time calling jsString inside RegExpObjectImp::arrayOfMatches to generate the match array. But nothing in the test uses the match array, except to test if it is null or not. So, we could make a special lazy array subclass that fills in the array only if you request any of the matches. (Total time in stringProtoFuncMatch is 6.8%, there could be more to juice here - also, since this is the major source of garbage strings, it should reduce all the time we are spending in StringImp::~StringImp.

2) 1% of time is spent in KJS::resolve_skip, likely much of this is retrieving the global &quot;document&quot; property, though some of it is &quot;Date&quot;. Since &quot;document&quot; is DontDelete and very commonly accessed, we could create it at the time the Window is created and statically put it in a var slot much like the Math object.

3) JSNode::getOwnPropertySlot and JSEventTarget::getOwnPropertySlot show up with self time, but are always called from a parent - should proably be inlined.

4) 0.2% of time calling strlen making a String from a char* in Node::textContent. Yuck. We should pre-make these strings.

5) 0.7% in Node::isReadOnlyNode(). This is solely to support entity and entity reference nodes in the DOM. But we expand entities so this doesn&apos;t normally even happen. So it sucks that we have to do this expensive check always at DOM mutation time. Unfortunately there are no spare bits in Node. However, Element has a 3-bit bitfield, so we could move a flag that only applies to Element (such as m_tabIndexSetExplicitly) and then have an m_readOnly flag which is set only for EntityReference and Entity nodes (they will never have children so no need to do propagation to their descendants). Alternately we could just make isReadOnlyNode inline and always returning false.

</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>81388</commentid>
    <comment_count>27</comment_count>
    <who name="Alexey Proskuryakov">ap</who>
    <bug_when>2008-05-24 14:34:29 -0700</bug_when>
    <thetext>(In reply to comment #26)
&gt; 1)  RegExpObjectImp::arrayOfMatches

Did that, testing now.

&gt; 4) 0.2% of time calling strlen making a String from a char* in
&gt; Node::textContent. Yuck. We should pre-make these strings.

Did that and more in &lt;http://trac.webkit.org/changeset/34108&gt;.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>81396</commentid>
    <comment_count>28</comment_count>
    <who name="Darin Adler">darin</who>
    <bug_when>2008-05-24 21:49:34 -0700</bug_when>
    <thetext>(In reply to comment #26)
&gt; 5) 0.7% in Node::isReadOnlyNode(). This is solely to support entity and entity
&gt; reference nodes in the DOM. But we expand entities so this doesn&apos;t normally
&gt; even happen. So it sucks that we have to do this expensive check always at DOM
&gt; mutation time. Unfortunately there are no spare bits in Node. However, Element
&gt; has a 3-bit bitfield, so we could move a flag that only applies to Element
&gt; (such as m_tabIndexSetExplicitly) and then have an m_readOnly flag which is set
&gt; only for EntityReference and Entity nodes (they will never have children so no
&gt; need to do propagation to their descendants). Alternately we could just make
&gt; isReadOnlyNode inline and always returning false.

I&apos;d love to make isReadOnlyNode inline and always return false. But there&apos;s a problem with that. We do support the Document::createEntityReference function. So while there is a guarantee there are no Entity nodes in the DOM tree, there is no such guarantee for EntityReference nodes.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>81397</commentid>
    <comment_count>29</comment_count>
    <who name="Darin Adler">darin</who>
    <bug_when>2008-05-24 22:03:10 -0700</bug_when>
    <thetext>(In reply to comment #28)
&gt; We do support the Document::createEntityReference function.

On the other hand, that function is useless, because we don&apos;t do the work to look up the entity and insert child nodes, which is how it&apos;s supposed to work. I think it&apos;d be better if we didn&apos;t half-support that function.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>81423</commentid>
    <comment_count>30</comment_count>
    <who name="Ian &apos;Hixie&apos; Hickson">ian</who>
    <bug_when>2008-05-25 00:08:31 -0700</bug_when>
    <thetext>If we get the Web DOM Core effort off the ground, I plan to advocate for the removal of EntityReference and Attr nodes outright, fwiw. Lack of support and removal of support in browsers is a good start. :-)</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>81437</commentid>
    <comment_count>31</comment_count>
    <who name="Maciej Stachowiak">mjs</who>
    <bug_when>2008-05-25 06:37:38 -0700</bug_when>
    <thetext>I have a fix for this one:

&gt; 2) 1% of time is spent in KJS::resolve_skip, likely much of this is retrieving
&gt; the global &quot;document&quot; property, though some of it is &quot;Date&quot;. Since &quot;document&quot;
&gt; is DontDelete and very commonly accessed, we could create it at the time the
&gt; Window is created and statically put it in a var slot much like the Math
&gt; object.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>81463</commentid>
    <comment_count>32</comment_count>
    <who name="Darin Adler">darin</who>
    <bug_when>2008-05-25 12:34:43 -0700</bug_when>
    <thetext>(In reply to comment #26)
&gt; 5) 0.7% in Node::isReadOnlyNode().

I have a patch that cuts this down to about 0.1% attached to the related bug. (I noticed unnecessary multiple calls to nodeType() in Node::appendTextContent.)

Other optimization thoughts (not the kind of great ideas Maciej posted, but still perhaps useful):

A) 1.5% of the time is taken converting the string &quot;class&quot; from a UString to an AtomicString. If we could find some way to not search the hash table over and over again here, that&apos;d be a big win.

B) DOM getOwnPropertySlot functions are taking a lot of time, more than 5%. The big costs are the PIC branch used to get access to the global table and the memory accesses in that table. And the size for the hash table for JSDOMNode, for example, is huge -- 4096 slots for the 19 values just to avoid the need to rehash. Maybe there&apos;s a better data structure we can use?

C) Overhead for render objects we never end up rendering is still a big part of the profile, even with Maciej&apos;s tear-down optimization. For example, CSSStyleSelector::styleForElement is 4.7% of the time and the total time for createRendererIfNeeded is 12.5%. And this is all for an element that&apos;s going to be removed before the next layout. If we can find a way to defer creating the renderer and never end up doing it at all then we will get a *big* speedup. Maybe we can change things so that renderers can be created at layout time.

D) Tons of time is spent inside toJS, making wrappers for the text node and HTMLAnchorElement objects that are created and looking for the existing wrapper for the result of parentNode, nextSibling, and others. We could cut down a lot of hash table overhead if we were willing to put a pointer in every WebCore::Node to the corresponding JSNode

E) We could avoid making a lot of JS string wrappers if we could create code paths that would keep the UString in the engine register until the value needs to be used as a generic value. The expression &quot;iteration &quot; + i + &quot; failed&quot; results in creation of many string wrappers and it&apos;s never used for anything at all. Similarly, the expression &quot;iteration &quot; + i + &quot; at &quot; + d results in the creation of many string wrappers and ultimately it&apos;s passed to createTextNode, which takes a string parameter rather than an arbitrary object value. I suspect that we could speed up by more than 5% by reducing the number of string wrappers if we could get the strings to the &quot;+&quot; operator and to the function call without converting to a wrapper, but that&apos;s probably a tall order.

F) The StringImp::toString function, 0.5%, would benefit from omit-frame-pointer.

G) The defaultValue function doesn&apos;t need to be a virtual function. Right now the bridge is using a custom implementation of defaultValue, but that&apos;s not really helpful. In fact, some of the overrides are actually using the wrong function signature (including ExecState*)! On the other hand, what&apos;s really slow here is all the overhead for doing a function call, and that&apos;s probably due to the crazy toString/defaultValue test case that&apos;s in test 26, so it might not be easy to optimize.

H) 0.6% of the time is in Document::body(). We can easily add code so that&apos;s cached.

I) We spend considerable time repeatedly checking if &quot;class&quot; is a valid name. Maybe we can cache that. We also pay function overhead to get the length and characters pointer from a String object. Those should probably be inlined.

J) Frame::page() is 0.3% -- we should probably move the page pointer from the private pointer to the top level of the Frame object and then inline the getter.

K) Inside the code to implement new Date we spend a lot of time in the floor inside getCurrentUTCTime. This could be avoided by dividing changing that code path tv_usec by 1000 as an integer operation instead of a floating point one. That&apos;s only 0.1% though.

L) NumberImp::toObject is taking 0.7% of the time. That&apos;s all being done to call toString() on the value of the date. Is there a way to avoid the toObject in that op_get_by_id opcode when it&apos;s a built-in function on Number? We already have to branch to convert to an object, but we could use that branch to instead go to a special version of the get operation for the non-object JavaScript types that avoids creating an object. Seems like it could be a 1% speedup.

M) documentBeingDestroyed() is showing up as 0.2% on the profile. It&apos;s simple and can be inlined.

N) It looks like the empty case of ~PropertyMap should be inlined. The 0.2% time spent in that function seems to all in that empty case.

O) numerProtoFuncToString could be changed around so that the &quot;no radix passed&quot; case is slightly faster for up to a 0.3% speedup.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>81487</commentid>
    <comment_count>33</comment_count>
    <who name="Maciej Stachowiak">mjs</who>
    <bug_when>2008-05-25 14:51:47 -0700</bug_when>
    <thetext>(In reply to comment #32)
&gt; (In reply to comment #26)
&gt; &gt; 5) 0.7% in Node::isReadOnlyNode().
&gt; 
&gt; I have a patch that cuts this down to about 0.1% attached to the related bug.
&gt; (I noticed unnecessary multiple calls to nodeType() in
&gt; Node::appendTextContent.)
&gt; 
&gt; Other optimization thoughts (not the kind of great ideas Maciej posted, but
&gt; still perhaps useful):

Comments on a few of these.

&gt; B) DOM getOwnPropertySlot functions are taking a lot of time, more than 5%. The
&gt; big costs are the PIC branch used to get access to the global table and the
&gt; memory accesses in that table. And the size for the hash table for JSDOMNode,
&gt; for example, is huge -- 4096 slots for the 19 values just to avoid the need to
&gt; rehash. Maybe there&apos;s a better data structure we can use?

I think just inlining some of them (especially the Node and EventTargetNode ones, which are never called directly) would help.

&gt; C) Overhead for render objects we never end up rendering is still a big part of
&gt; the profile, even with Maciej&apos;s tear-down optimization. For example,
&gt; CSSStyleSelector::styleForElement is 4.7% of the time and the total time for
&gt; createRendererIfNeeded is 12.5%. And this is all for an element that&apos;s going to
&gt; be removed before the next layout. If we can find a way to defer creating the
&gt; renderer and never end up doing it at all then we will get a *big* speedup.
&gt; Maybe we can change things so that renderers can be created at layout time.

I have thought about this but I am not sure it is good for the normal case.

&gt; D) Tons of time is spent inside toJS, making wrappers for the text node and
&gt; HTMLAnchorElement objects that are created and looking for the existing wrapper
&gt; for the result of parentNode, nextSibling, and others. We could cut down a lot
&gt; of hash table overhead if we were willing to put a pointer in every
&gt; WebCore::Node to the corresponding JSNode.

I think two things would speed this up a fair bit without the extra pointer:

D.i) Make a version of toJS that takes a node which is known to be newly created, and in that case skip the hash lookup for the existing wrapper, since there can&apos;t be one.

D.ii) Add type-spepcific overload for Text* and perhaps Element* or even HTMLElement* to avoid dispatching on the node type in the newly created case.

&gt; E) We could avoid making a lot of JS string wrappers if we could create code
&gt; paths that would keep the UString in the engine register until the value needs
&gt; to be used as a generic value. The expression &quot;iteration &quot; + i + &quot; failed&quot;
&gt; results in creation of many string wrappers and it&apos;s never used for anything at
&gt; all. Similarly, the expression &quot;iteration &quot; + i + &quot; at &quot; + d results in the
&gt; creation of many string wrappers and ultimately it&apos;s passed to createTextNode,
&gt; which takes a string parameter rather than an arbitrary object value. I suspect
&gt; that we could speed up by more than 5% by reducing the number of string
&gt; wrappers if we could get the strings to the &quot;+&quot; operator and to the function
&gt; call without converting to a wrapper, but that&apos;s probably a tall order.

I think we can make a significant improvement without changing the register representation, and adding only two opcodes. But I am not sure how general the optimization is. Here&apos;s the idea:

a) The condition for this to apply is an AddNode chain where the leftmost operand is a constant string (this means every addition is a string add). You have to be careful though because &quot;xx&quot; + (i + z) can&apos;t assume all string adds.

b) In this case, emit code to load the constant string operands and convert non-string operands to string (with a new tostring opcode) to sequential registers.

c) Emit a new append_strings opcode which assumes all operands are primitive strings, and concatenates them at one go into a fresh UString. This would both reduce allocation work in UString (can do multiple appends all at once) and reduce the number of temporaries created (in &quot;iteration &quot; + i + &quot; at &quot; + d, i and d are still converted to string resulting in temporaries, but the GC values for &quot;iteration &quot; + i and &quot;iteration &quot; + i + &quot; at &quot; need never be created, cutting the number of unobserved string temporaries in half).

I am not sure whether this optimization is general enough to be worth adding two opcodes.

&gt; L) NumberImp::toObject is taking 0.7% of the time. That&apos;s all being done to
&gt; call toString() on the value of the date. Is there a way to avoid the toObject
&gt; in that op_get_by_id opcode when it&apos;s a built-in function on Number? We already
&gt; have to branch to convert to an object, but we could use that branch to instead
&gt; go to a special version of the get operation for the non-object JavaScript
&gt; types that avoids creating an object. Seems like it could be a 1% speedup.

It&apos;s possible to optimize property access on primitives, but a bit tricky. If the property turns out to be a manually added prototype method that uses the &quot;this&quot; value and possibly even stores it, then the toObject conversion has to actually happen on entry to that function. Geoff and I have discussed ideas how to do this. Note that this would in general help strings more than numbers. It would help some of the string tests on SunSpider quite a bit. I can give more detail if needed.
</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>81490</commentid>
    <comment_count>34</comment_count>
    <who name="Ian &apos;Hixie&apos; Hickson">ian</who>
    <bug_when>2008-05-25 15:44:23 -0700</bug_when>
    <thetext>I&apos;d like to echo the sentiment underlying mjs&apos; most recent comments -- when looking at optimisations here please consider how they would affect the real Web first. It doesn&apos;t matter how fast Acid3 is really, the idea is just that it might be a (poor) proxy for real Web usage.

Having said that, regarding the strings specifically, concatenating strings is pretty common. Why would that idea not generalise well?</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>81492</commentid>
    <comment_count>35</comment_count>
    <who name="Maciej Stachowiak">mjs</who>
    <bug_when>2008-05-25 16:11:59 -0700</bug_when>
    <thetext>(In reply to comment #33)
&gt; 
&gt; 
&gt; &gt; E) We could avoid making a lot of JS string wrappers if we could create code
&gt; &gt; paths that would keep the UString in the engine register until the value needs
&gt; &gt; to be used as a generic value. The expression &quot;iteration &quot; + i + &quot; failed&quot;
&gt; &gt; results in creation of many string wrappers and it&apos;s never used for anything at
&gt; &gt; all. Similarly, the expression &quot;iteration &quot; + i + &quot; at &quot; + d results in the
&gt; &gt; creation of many string wrappers and ultimately it&apos;s passed to createTextNode,
&gt; &gt; which takes a string parameter rather than an arbitrary object value. I suspect
&gt; &gt; that we could speed up by more than 5% by reducing the number of string
&gt; &gt; wrappers if we could get the strings to the &quot;+&quot; operator and to the function
&gt; &gt; call without converting to a wrapper, but that&apos;s probably a tall order.
&gt; 
&gt; I think we can make a significant improvement without changing the register
&gt; representation, and adding only two opcodes. But I am not sure how general the
&gt; optimization is. Here&apos;s the idea:

Some clarifiaction.

&gt; 
&gt; a) The condition for this to apply is an AddNode chain where the leftmost
&gt; operand is a constant string (this means every addition is a string add). You
&gt; have to be careful though because &quot;xx&quot; + (i + z) can&apos;t assume all string adds.
&gt; 
&gt; b) In this case, emit code to load the constant string operands and convert
&gt; non-string operands to string (with a new tostring opcode) to sequential
&gt; registers.

On second thought, the append_strings opcode could do any needed string conversion, so it could be done with only one extra opcode.

&gt; c) Emit a new append_strings opcode which assumes all operands are primitive
&gt; strings, and concatenates them at one go into a fresh UString. This would both
&gt; reduce allocation work in UString (can do multiple appends all at once) and
&gt; reduce the number of temporaries created (in &quot;iteration &quot; + i + &quot; at &quot; + d, i
&gt; and d are still converted to string resulting in temporaries, but the GC values
&gt; for &quot;iteration &quot; + i and &quot;iteration &quot; + i + &quot; at &quot; need never be created,
&gt; cutting the number of unobserved string temporaries in half).

The append_strings opcode would take a starting register and a register count (or ending register) as its parameters. Outputting to the right registers could be handled as for function call parameters.
</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>81493</commentid>
    <comment_count>36</comment_count>
    <who name="Maciej Stachowiak">mjs</who>
    <bug_when>2008-05-25 16:18:17 -0700</bug_when>
    <thetext>(In reply to comment #34)
&gt; I&apos;d like to echo the sentiment underlying mjs&apos; most recent comments -- when
&gt; looking at optimisations here please consider how they would affect the real
&gt; Web first. It doesn&apos;t matter how fast Acid3 is really, the idea is just that it
&gt; might be a (poor) proxy for real Web usage.

In all honesty the test 26 timing loop is not a very good real-world benchmark. As Darin mentions, one of the most effective ways to speed it up is to optimize handling of DOM nodes that are inserted into the document and then removed again before they can lay out or paint, something that very rarely happens in real situations. It is unlikely that highly effective general optimizations will take 26 into the win category, for instance our massive JS interpreter rewrite had minimal impact even though it speeds up many more realistic benchmarks by factors of 1.2x - 2.1x.

That being said, we&apos;d like to win anyway, and hopefully can do it with optimizations that at least do not harm the general case or may be useful for other reasons.

&gt; Having said that, regarding the strings specifically, concatenating strings is
&gt; pretty common. Why would that idea not generalise well?

It might. Note that my suggestion only covers some very specific patterns. For instance, these cases could not be optimized:

1) var s = x + y + &quot; some constant string&quot;;
2) var s = &quot;foo&quot;; s += x; s += y;
3) var s = &quot;foo&quot; + x; // no intermediate values avoided here

The question is how common such patterns are compared to var s = &quot;foo&quot; + x + y; or similar. If the optimizable pattern isn&apos;t that common as a hot spot in real code, then it is unwise to add complexity to the bytecode interpreter&apos;s main loop to handle it. I am not really sure of the frequency distribution.
</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>81500</commentid>
    <comment_count>37</comment_count>
      <attachid>21344</attachid>
    <who name="Maciej Stachowiak">mjs</who>
    <bug_when>2008-05-25 19:48:32 -0700</bug_when>
    <thetext>Created attachment 21344
not quite working version of optimizing &quot;document&quot; to a static slot

This still fails some layout tests. I probably have the timing wrong.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>81505</commentid>
    <comment_count>38</comment_count>
    <who name="Maciej Stachowiak">mjs</who>
    <bug_when>2008-05-25 20:19:25 -0700</bug_when>
    <thetext>Besides the obvious simple inlines and additional caches, I like D and L from Darin&apos;s ideas (as modified by my suggestions) though L is tricky to implement. E also sounds like it could be good, though maybe also tricky to implement.

I have a feeling we won&apos;t win this one without some form of C, but we will need some input from Hyatt.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>81534</commentid>
    <comment_count>39</comment_count>
    <who name="Geoffrey Garen">ggaren</who>
    <bug_when>2008-05-26 13:05:23 -0700</bug_when>
    <thetext>As for E, I believe that type specialization in the bytecode engine would naturally remove all string wrappers created by 

&quot;iteration &quot; + i + &quot; at &quot; + d

Since &quot;iteration&quot; and &quot; at &quot; are known strings at compile time, we know that this expression is a string add, so i and d should produce strings, not generic values.

We would still need to create a string wrapper for the sake of calling createTextNode, though. Specializing for the expected types of arbitrary DOM APIs would be very hard. (I&apos;m not even sure how we would do that.)</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>81550</commentid>
    <comment_count>40</comment_count>
    <who name="Maciej Stachowiak">mjs</who>
    <bug_when>2008-05-26 15:58:07 -0700</bug_when>
    <thetext>(In reply to comment #39)
&gt; As for E, I believe that type specialization in the bytecode engine would
&gt; naturally remove all string wrappers created by 
&gt; 
&gt; &quot;iteration &quot; + i + &quot; at &quot; + d
&gt; 
&gt; Since &quot;iteration&quot; and &quot; at &quot; are known strings at compile time, we know that
&gt; this expression is a string add, so i and d should produce strings, not generic
&gt; values.

i and d have to produce generic values first because they have to go through toString/valueOf. d in particular has a custom toString() function in this case, so that&apos;s not just a theoretical issue. This approach would in theory be able to remove the same temporary wrappers as my proposed multi-concatenation opcode, but not the UString temporaries. So I think optimizing multiple concatenations might be worthwhile even when we have type specialization.

&gt; We would still need to create a string wrapper for the sake of calling
&gt; createTextNode, though. Specializing for the expected types of arbitrary DOM
&gt; APIs would be very hard. (I&apos;m not even sure how we would do that.)

If registers are type-coded in an obvious way, then it could still be a UString in the arguments vector. However, UString is problematic to use in register values at all because of the refcounting. Unlike primitive values or JSValue*, when a register containing such a value is killed we&apos;d have to deref.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>81565</commentid>
    <comment_count>41</comment_count>
    <who name="Maciej Stachowiak">mjs</who>
    <bug_when>2008-05-26 22:37:52 -0700</bug_when>
    <thetext>I took a fresh profile and looked at a top-down view to get a rough estimate of how readily we can improve times on this test. We need to cut out approximately 23% of the current execution time (a 1.3x speedup).

Top-down, I see the following mutually exclusive categories of time:

7.5% self time in KJS::Machine::privateExecute (could potentially be reduced by optimizing JS)
16.8% total time in JSNode::insertBefore
8.5% total time in JSNode::removeChild
8.4% total time in JSObject::defaultValue
7.7% total time in jsString()
4.8% total time in JSElement::setAttribute
4.0% total time in jsDocumentPrototypeFunctionCreateElement
3.1% total time in stringProtoFuncMatch
3.1% total time in JSNode::getValueProperty
2.3% total time in JSNode::appendChild
2.0% total time in jsDocumentPrototypeFunctionCreateTextNode
1.6% total time in makeFunction
1.6% total time in UString concatenation constructor
1.5% total time in jsDocumentPrototypeFunctionGetElementById
1.3% total time in DateObjectImp::construct
1.1% total time in JSCharacterData::getValueProperty

Seems like optimizing string concatenation could plausibly remove half the jsString() time and half the UString constructor time so that is a plausible big win. Devirtualizing defaultValue could also be a good payoff. Reducing the insertBefore or removeChild time seems like a challenge though may be necessary to win.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>81566</commentid>
    <comment_count>42</comment_count>
      <attachid>21344</attachid>
    <who name="Maciej Stachowiak">mjs</who>
    <bug_when>2008-05-26 23:01:36 -0700</bug_when>
    <thetext>Comment on attachment 21344
not quite working version of optimizing &quot;document&quot; to a static slot

Obsoleting this, since I have landed a working version.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>82059</commentid>
    <comment_count>43</comment_count>
    <who name="Peter Neumayr">peter.neumayr</who>
    <bug_when>2008-06-01 08:50:27 -0700</bug_when>
    <thetext>With the latest nightly build (34279) the test passes on my MacBook in most cases, in some cases test 26 takes up to 37ms, but since a 2GHz dual-core MacBook should be considerable slower than the latest state of the art apple laptop, this should be ok. So, how fast do you want to be until announcing that you&apos;ve won the race?</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>82462</commentid>
    <comment_count>44</comment_count>
    <who name="Mark Rowe (bdash)">mrowe</who>
    <bug_when>2008-06-06 14:51:27 -0700</bug_when>
    <thetext>With TOT WebKit, test 26 passes comfortably on a 2.4GHz MacBook Pro, which is slower than what Hixie has chosen as the reference hardware for the performance aspect of the test.  Closing as fixed.</thetext>
  </long_desc>
      
          <attachment
              isobsolete="1"
              ispatch="0"
              isprivate="0"
          >
            <attachid>19820</attachid>
            <date>2008-03-16 19:54:56 -0700</date>
            <delta_ts>2008-05-23 20:25:31 -0700</delta_ts>
            <desc>Standalone version of test 26, for profiling goodness</desc>
            <filename>acid3-test26.html</filename>
            <type>text/html</type>
            <size>3681</size>
            <attacher name="Maciej Stachowiak">mjs</attacher>
            
              <data encoding="base64">ICA8ZGl2IGNsYXNzPSJidWNrZXRzIgogICA+PHAgaWQ9ImJ1Y2tldDEiIGNsYXNzPSJ6Ij48L3AK
ICAgPjxwIGlkPSJidWNrZXQyIiBjbGFzcz0ieiI+PC9wCiAgID48cCBpZD0iYnVja2V0MyIgY2xh
c3M9InoiPjwvcAogICA+PHAgaWQ9ImJ1Y2tldDQiIGNsYXNzPSJ6Ij48L3AKICAgPjxwIGlkPSJi
dWNrZXQ1IiBjbGFzcz0ieiI+PC9wCiAgID48cCBpZD0iYnVja2V0NiIgY2xhc3M9InoiPjwvcD4K
ICA8L2Rpdj4KPHNjcmlwdD4KaWYgKHdpbmRvdy5sYXlvdXRUZXN0Q29udHJvbGxlcikgewogICAg
bGF5b3V0VGVzdENvbnRyb2xsZXIuZHVtcEFzVGV4dCgpOwp9Cjwvc2NyaXB0Pgo8c2NyaXB0Pgp2
YXIgc3RhcnQgPSBuZXcgRGF0ZSgpOwoKICBmdW5jdGlvbiBmYWlsKG1lc3NhZ2UpIHsKICAgICAg
ZG9jdW1lbnQud3JpdGUobWVzc2FnZSArICI8YnI+Iik7CiAgfQogIGZ1bmN0aW9uIGFzc2VydChj
b25kaXRpb24sIG1lc3NhZ2UpIHsKICAgIGlmICghY29uZGl0aW9uKQogICAgICBmYWlsKG1lc3Nh
Z2UpOwogIH0KICBmdW5jdGlvbiBhc3NlcnRFcXVhbHMoZXhwcmVzc2lvbiwgdmFsdWUsIG1lc3Nh
Z2UpIHsKICAgIGlmIChleHByZXNzaW9uICE9IHZhbHVlKSB7CiAgICAgIGV4cHJlc3Npb24gPSAo
IiIrZXhwcmVzc2lvbikucmVwbGFjZSgvW1xyXG5dKy9nLCAiXFxuIik7CiAgICAgIHZhbHVlID0g
KCIiK3ZhbHVlKS5yZXBsYWNlKC9ccj9cbi9nLCAiXFxuIik7CiAgICAgIGZhaWwoImV4cGVjdGVk
OiAiICsgdmFsdWUgKyAiLCBnb3Q6ICIgKyBleHByZXNzaW9uICsgIiAtICIgKyBtZXNzYWdlKTsK
ICAgIH0KICB9CgoKICAgICAgLy8gdGVzdCAyNjogY2hlY2sgdGhhdCBkb2N1bWVudCB0cmVlIHN1
cnZpdmVzIHdoaWxlIHN0aWxsIGFjY2Vzc2libGUKICAgICAgdmFyIGQ7CiAgICAgIC8vIGUxIC0g
YW4gZWxlbWVudCB0aGF0J3MgaW4gYSBkb2N1bWVudAogICAgICBkID0gZG9jdW1lbnQuaW1wbGVt
ZW50YXRpb24uY3JlYXRlRG9jdW1lbnQobnVsbCwgbnVsbCwgbnVsbCk7CiAgICAgIHZhciBlMSA9
IGQuY3JlYXRlRWxlbWVudCgndGVzdCcpOwogICAgICBkLmFwcGVuZENoaWxkKGQuY3JlYXRlRWxl
bWVudCgncm9vdCcpKTsKICAgICAgZC5kb2N1bWVudEVsZW1lbnQuYXBwZW5kQ2hpbGQoZTEpOwog
ICAgICBhc3NlcnQoZTEucGFyZW50Tm9kZSwgImUxIC0gcGFyZW50IGVsZW1lbnQgZG9lc24ndCBl
eGlzdCIpOwogICAgICBhc3NlcnQoZTEucGFyZW50Tm9kZS5vd25lckRvY3VtZW50LCAiZTEgLSBk
b2N1bWVudCBkb2Vzbid0IGV4aXN0Iik7CiAgICAgIC8vIGUyIC0gYW4gZWxlbWVudCB0aGF0J3Mg
bm90IGluIGEgZG9jdW1lbnQKICAgICAgZCA9IGRvY3VtZW50LmltcGxlbWVudGF0aW9uLmNyZWF0
ZURvY3VtZW50KG51bGwsIG51bGwsIG51bGwpOwogICAgICB2YXIgZTIgPSBkLmNyZWF0ZUVsZW1l
bnQoJ3Rlc3QnKTsKICAgICAgZC5jcmVhdGVFbGVtZW50KCdyb290JykuYXBwZW5kQ2hpbGQoZTIp
OwogICAgICBhc3NlcnQoZTIucGFyZW50Tm9kZSwgImUyIC0gcGFyZW50IGVsZW1lbnQgZG9lc24n
dCBleGlzdCIpOwogICAgICBhc3NlcnQoZTIucGFyZW50Tm9kZS5vd25lckRvY3VtZW50LCAiZTIg
LSBkb2N1bWVudCBkb2Vzbid0IGV4aXN0Iik7CiAgICAgIC8vIG5vdyB0cnkgdG8gZGVjb3VwbGUg
dGhlbQogICAgICBkID0gbnVsbDsKICAgICAga3VuZ0Z1RGVhdGhHcmlwID0gW2UxLCBlMl07CiAg
ICAgIGFzc2VydChlMS5wYXJlbnROb2RlLCAiZTEgLSBwYXJlbnQgZWxlbWVudCBkb2Vzbid0IGV4
aXN0IGFmdGVyIGRyb3BwaW5nIHJlZmVyZW5jZSB0byBkb2N1bWVudCIpOwogICAgICBhc3NlcnQo
ZTEucGFyZW50Tm9kZS5vd25lckRvY3VtZW50LCAiZTEgLSBkb2N1bWVudCBkb2Vzbid0IGV4aXN0
IGFmdGVyIGRyb3BwaW5nIHJlZmVyZW5jZSB0byBkb2N1bWVudCIpOwogICAgICBhc3NlcnQoZTIu
cGFyZW50Tm9kZSwgImUyIC0gcGFyZW50IGVsZW1lbnQgZG9lc24ndCBleGlzdCBhZnRlciBkcm9w
cGluZyByZWZlcmVuY2UgdG8gZG9jdW1lbnQiKTsKICAgICAgYXNzZXJ0KGUyLnBhcmVudE5vZGUu
b3duZXJEb2N1bWVudCwgImUyIC0gZG9jdW1lbnQgZG9lc24ndCBleGlzdCBhZnRlciBkcm9wcGlu
ZyByZWZlcmVuY2UgdG8gZG9jdW1lbnQiKTsKICAgICAgdmFyIGxvb3BzID0gbmV3IERhdGUoKS52
YWx1ZU9mKCkgKiA1ZS05IC0gNDI1MDsgLy8gaW5jcmVhc2VzIGxpbmVhcmx5IG92ZXIgdGltZQog
ICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxvb3BzOyBpICs9IDEpIHsKICAgICAgICAvLyB3ZSB3
YW50IHRvIGZvcmNlIGEgR0MgaGVyZSwgc28gd2UgdXNlIHVwIGxvdHMgb2YgbWVtb3J5CiAgICAg
ICAgLy8gd2UgdGFrZSB0aGUgb3Bwb3J0dW5pdHkgdG8gc25lYWsgaW4gYSBwZXJmIHRlc3QgdG8g
bWFrZSBET00gYW5kIEpTIHN0dWZmIGZhc3Rlci4uLgogICAgICAgIGQgPSBuZXcgRGF0ZSgpOwog
ICAgICAgIGQgPSBuZXcgKGZ1bmN0aW9uICh4KSB7IHJldHVybiB7IHRvU3RyaW5nOiBmdW5jdGlv
biAoKSB7IHJldHVybiB4LnRvU3RyaW5nKCkgfSB9IH0pKGQudmFsdWVPZigpKTsKICAgICAgICBk
ID0gZG9jdW1lbnQuY3JlYXRlVGV4dE5vZGUoIml0ZXJhdGlvbiAiICsgaSArICIgYXQgIiArIGQp
OwogICAgICAgIGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2EnKS5hcHBlbmRDaGlsZChkKTsKICAg
ICAgICBkID0gZC5wYXJlbnROb2RlOwogICAgICAgIGRvY3VtZW50LmJvZHkuaW5zZXJ0QmVmb3Jl
KGQsIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdidWNrZXQxJykucGFyZW50Tm9kZSk7CiAgICAg
ICAgYXNzZXJ0KGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdidWNrZXQyJykubmV4dFNpYmxpbmcu
cGFyZW50Tm9kZS5wcmV2aW91c1NpYmxpbmcuZmlyc3RDaGlsZC5kYXRhLm1hdGNoKC9BVFxXL2kp
LCAiaXRlcmF0aW9uICIgKyBpICsgIiBmYWlsZWQiKTsKICAgICAgICBkLnNldEF0dHJpYnV0ZSgn
Y2xhc3MnLCBkLnRleHRDb250ZW50KTsKICAgICAgICBkb2N1bWVudC5ib2R5LnJlbW92ZUNoaWxk
KGQpOwogICAgICB9CiAgICAgIGFzc2VydChlMS5wYXJlbnROb2RlLCAiZTEgLSBwYXJlbnQgZWxl
bWVudCBkb2Vzbid0IGV4aXN0IGFmdGVyIGxvb3BpbmciKTsKICAgICAgYXNzZXJ0KGUxLnBhcmVu
dE5vZGUub3duZXJEb2N1bWVudCwgImUxIC0gZG9jdW1lbnQgZG9lc24ndCBleGlzdCBhZnRlciBs
b29waW5nIik7CiAgICAgIGFzc2VydEVxdWFscyhlMS5wYXJlbnROb2RlLm93bmVyRG9jdW1lbnQu
bm9kZVR5cGUsIDksICJlMSAtIGRvY3VtZW50IG5vZGUgdHlwZSBoYXMgd3Jvbmcgbm9kZSB0eXBl
Iik7CiAgICAgIGFzc2VydChlMi5wYXJlbnROb2RlLCAiZTIgLSBwYXJlbnQgZWxlbWVudCBkb2Vz
bid0IGV4aXN0IGFmdGVyIGxvb3BpbmciKTsKICAgICAgYXNzZXJ0KGUyLnBhcmVudE5vZGUub3du
ZXJEb2N1bWVudCwgImUyIC0gZG9jdW1lbnQgZG9lc24ndCBleGlzdCBhZnRlciBsb29waW5nIik7
CiAgICAgIGFzc2VydEVxdWFscyhlMi5wYXJlbnROb2RlLm93bmVyRG9jdW1lbnQubm9kZVR5cGUs
IDksICJlMiAtIGRvY3VtZW50IG5vZGUgdHlwZSBoYXMgd3Jvbmcgbm9kZSB0eXBlIik7Cgp2YXIg
ZHVyYXRpb24gPSBuZXcgRGF0ZSgpIC0gc3RhcnQ7CmRvY3VtZW50LndyaXRlKCJUZXN0IHRvb2s6
ICIgKyBkdXJhdGlvbiArICJtcyIpOwo8L3NjcmlwdD4K
</data>

          </attachment>
          <attachment
              isobsolete="1"
              ispatch="0"
              isprivate="0"
          >
            <attachid>19858</attachid>
            <date>2008-03-17 21:41:58 -0700</date>
            <delta_ts>2008-05-23 20:25:31 -0700</delta_ts>
            <desc>alternate version, larger, non-variable loop count so easier to profile</desc>
            <filename>acid3-test26-for-profiling.html</filename>
            <type>text/html</type>
            <size>3620</size>
            <attacher name="Darin Adler">darin</attacher>
            
              <data encoding="base64">ICA8ZGl2IGNsYXNzPSJidWNrZXRzIgogICA+PHAgaWQ9ImJ1Y2tldDEiIGNsYXNzPSJ6Ij48L3AK
ICAgPjxwIGlkPSJidWNrZXQyIiBjbGFzcz0ieiI+PC9wCiAgID48cCBpZD0iYnVja2V0MyIgY2xh
c3M9InoiPjwvcAogICA+PHAgaWQ9ImJ1Y2tldDQiIGNsYXNzPSJ6Ij48L3AKICAgPjxwIGlkPSJi
dWNrZXQ1IiBjbGFzcz0ieiI+PC9wCiAgID48cCBpZD0iYnVja2V0NiIgY2xhc3M9InoiPjwvcD4K
ICA8L2Rpdj4KPHNjcmlwdD4KaWYgKHdpbmRvdy5sYXlvdXRUZXN0Q29udHJvbGxlcikgewogICAg
bGF5b3V0VGVzdENvbnRyb2xsZXIuZHVtcEFzVGV4dCgpOwp9Cjwvc2NyaXB0Pgo8c2NyaXB0Pgp2
YXIgc3RhcnQgPSBuZXcgRGF0ZSgpOwoKICBmdW5jdGlvbiBmYWlsKG1lc3NhZ2UpIHsKICAgICAg
ZG9jdW1lbnQud3JpdGUobWVzc2FnZSArICI8YnI+Iik7CiAgfQogIGZ1bmN0aW9uIGFzc2VydChj
b25kaXRpb24sIG1lc3NhZ2UpIHsKICAgIGlmICghY29uZGl0aW9uKQogICAgICBmYWlsKG1lc3Nh
Z2UpOwogIH0KICBmdW5jdGlvbiBhc3NlcnRFcXVhbHMoZXhwcmVzc2lvbiwgdmFsdWUsIG1lc3Nh
Z2UpIHsKICAgIGlmIChleHByZXNzaW9uICE9IHZhbHVlKSB7CiAgICAgIGV4cHJlc3Npb24gPSAo
IiIrZXhwcmVzc2lvbikucmVwbGFjZSgvW1xyXG5dKy9nLCAiXFxuIik7CiAgICAgIHZhbHVlID0g
KCIiK3ZhbHVlKS5yZXBsYWNlKC9ccj9cbi9nLCAiXFxuIik7CiAgICAgIGZhaWwoImV4cGVjdGVk
OiAiICsgdmFsdWUgKyAiLCBnb3Q6ICIgKyBleHByZXNzaW9uICsgIiAtICIgKyBtZXNzYWdlKTsK
ICAgIH0KICB9CgoKICAgICAgLy8gdGVzdCAyNjogY2hlY2sgdGhhdCBkb2N1bWVudCB0cmVlIHN1
cnZpdmVzIHdoaWxlIHN0aWxsIGFjY2Vzc2libGUKICAgICAgdmFyIGQ7CiAgICAgIC8vIGUxIC0g
YW4gZWxlbWVudCB0aGF0J3MgaW4gYSBkb2N1bWVudAogICAgICBkID0gZG9jdW1lbnQuaW1wbGVt
ZW50YXRpb24uY3JlYXRlRG9jdW1lbnQobnVsbCwgbnVsbCwgbnVsbCk7CiAgICAgIHZhciBlMSA9
IGQuY3JlYXRlRWxlbWVudCgndGVzdCcpOwogICAgICBkLmFwcGVuZENoaWxkKGQuY3JlYXRlRWxl
bWVudCgncm9vdCcpKTsKICAgICAgZC5kb2N1bWVudEVsZW1lbnQuYXBwZW5kQ2hpbGQoZTEpOwog
ICAgICBhc3NlcnQoZTEucGFyZW50Tm9kZSwgImUxIC0gcGFyZW50IGVsZW1lbnQgZG9lc24ndCBl
eGlzdCIpOwogICAgICBhc3NlcnQoZTEucGFyZW50Tm9kZS5vd25lckRvY3VtZW50LCAiZTEgLSBk
b2N1bWVudCBkb2Vzbid0IGV4aXN0Iik7CiAgICAgIC8vIGUyIC0gYW4gZWxlbWVudCB0aGF0J3Mg
bm90IGluIGEgZG9jdW1lbnQKICAgICAgZCA9IGRvY3VtZW50LmltcGxlbWVudGF0aW9uLmNyZWF0
ZURvY3VtZW50KG51bGwsIG51bGwsIG51bGwpOwogICAgICB2YXIgZTIgPSBkLmNyZWF0ZUVsZW1l
bnQoJ3Rlc3QnKTsKICAgICAgZC5jcmVhdGVFbGVtZW50KCdyb290JykuYXBwZW5kQ2hpbGQoZTIp
OwogICAgICBhc3NlcnQoZTIucGFyZW50Tm9kZSwgImUyIC0gcGFyZW50IGVsZW1lbnQgZG9lc24n
dCBleGlzdCIpOwogICAgICBhc3NlcnQoZTIucGFyZW50Tm9kZS5vd25lckRvY3VtZW50LCAiZTIg
LSBkb2N1bWVudCBkb2Vzbid0IGV4aXN0Iik7CiAgICAgIC8vIG5vdyB0cnkgdG8gZGVjb3VwbGUg
dGhlbQogICAgICBkID0gbnVsbDsKICAgICAga3VuZ0Z1RGVhdGhHcmlwID0gW2UxLCBlMl07CiAg
ICAgIGFzc2VydChlMS5wYXJlbnROb2RlLCAiZTEgLSBwYXJlbnQgZWxlbWVudCBkb2Vzbid0IGV4
aXN0IGFmdGVyIGRyb3BwaW5nIHJlZmVyZW5jZSB0byBkb2N1bWVudCIpOwogICAgICBhc3NlcnQo
ZTEucGFyZW50Tm9kZS5vd25lckRvY3VtZW50LCAiZTEgLSBkb2N1bWVudCBkb2Vzbid0IGV4aXN0
IGFmdGVyIGRyb3BwaW5nIHJlZmVyZW5jZSB0byBkb2N1bWVudCIpOwogICAgICBhc3NlcnQoZTIu
cGFyZW50Tm9kZSwgImUyIC0gcGFyZW50IGVsZW1lbnQgZG9lc24ndCBleGlzdCBhZnRlciBkcm9w
cGluZyByZWZlcmVuY2UgdG8gZG9jdW1lbnQiKTsKICAgICAgYXNzZXJ0KGUyLnBhcmVudE5vZGUu
b3duZXJEb2N1bWVudCwgImUyIC0gZG9jdW1lbnQgZG9lc24ndCBleGlzdCBhZnRlciBkcm9wcGlu
ZyByZWZlcmVuY2UgdG8gZG9jdW1lbnQiKTsKICAgICAgdmFyIGxvb3BzID0gNTAwMDA7CiAgICAg
IGZvciAodmFyIGkgPSAwOyBpIDwgbG9vcHM7IGkgKz0gMSkgewogICAgICAgIC8vIHdlIHdhbnQg
dG8gZm9yY2UgYSBHQyBoZXJlLCBzbyB3ZSB1c2UgdXAgbG90cyBvZiBtZW1vcnkKICAgICAgICAv
LyB3ZSB0YWtlIHRoZSBvcHBvcnR1bml0eSB0byBzbmVhayBpbiBhIHBlcmYgdGVzdCB0byBtYWtl
IERPTSBhbmQgSlMgc3R1ZmYgZmFzdGVyLi4uCiAgICAgICAgZCA9IG5ldyBEYXRlKCk7CiAgICAg
ICAgZCA9IG5ldyAoZnVuY3Rpb24gKHgpIHsgcmV0dXJuIHsgdG9TdHJpbmc6IGZ1bmN0aW9uICgp
IHsgcmV0dXJuIHgudG9TdHJpbmcoKSB9IH0gfSkoZC52YWx1ZU9mKCkpOwogICAgICAgIGQgPSBk
b2N1bWVudC5jcmVhdGVUZXh0Tm9kZSgiaXRlcmF0aW9uICIgKyBpICsgIiBhdCAiICsgZCk7CiAg
ICAgICAgZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnYScpLmFwcGVuZENoaWxkKGQpOwogICAgICAg
IGQgPSBkLnBhcmVudE5vZGU7CiAgICAgICAgZG9jdW1lbnQuYm9keS5pbnNlcnRCZWZvcmUoZCwg
ZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2J1Y2tldDEnKS5wYXJlbnROb2RlKTsKICAgICAgICBh
c3NlcnQoZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2J1Y2tldDInKS5uZXh0U2libGluZy5wYXJl
bnROb2RlLnByZXZpb3VzU2libGluZy5maXJzdENoaWxkLmRhdGEubWF0Y2goL0FUXFcvaSksICJp
dGVyYXRpb24gIiArIGkgKyAiIGZhaWxlZCIpOwogICAgICAgIGQuc2V0QXR0cmlidXRlKCdjbGFz
cycsIGQudGV4dENvbnRlbnQpOwogICAgICAgIGRvY3VtZW50LmJvZHkucmVtb3ZlQ2hpbGQoZCk7
CiAgICAgIH0KICAgICAgYXNzZXJ0KGUxLnBhcmVudE5vZGUsICJlMSAtIHBhcmVudCBlbGVtZW50
IGRvZXNuJ3QgZXhpc3QgYWZ0ZXIgbG9vcGluZyIpOwogICAgICBhc3NlcnQoZTEucGFyZW50Tm9k
ZS5vd25lckRvY3VtZW50LCAiZTEgLSBkb2N1bWVudCBkb2Vzbid0IGV4aXN0IGFmdGVyIGxvb3Bp
bmciKTsKICAgICAgYXNzZXJ0RXF1YWxzKGUxLnBhcmVudE5vZGUub3duZXJEb2N1bWVudC5ub2Rl
VHlwZSwgOSwgImUxIC0gZG9jdW1lbnQgbm9kZSB0eXBlIGhhcyB3cm9uZyBub2RlIHR5cGUiKTsK
ICAgICAgYXNzZXJ0KGUyLnBhcmVudE5vZGUsICJlMiAtIHBhcmVudCBlbGVtZW50IGRvZXNuJ3Qg
ZXhpc3QgYWZ0ZXIgbG9vcGluZyIpOwogICAgICBhc3NlcnQoZTIucGFyZW50Tm9kZS5vd25lckRv
Y3VtZW50LCAiZTIgLSBkb2N1bWVudCBkb2Vzbid0IGV4aXN0IGFmdGVyIGxvb3BpbmciKTsKICAg
ICAgYXNzZXJ0RXF1YWxzKGUyLnBhcmVudE5vZGUub3duZXJEb2N1bWVudC5ub2RlVHlwZSwgOSwg
ImUyIC0gZG9jdW1lbnQgbm9kZSB0eXBlIGhhcyB3cm9uZyBub2RlIHR5cGUiKTsKCnZhciBkdXJh
dGlvbiA9IG5ldyBEYXRlKCkgLSBzdGFydDsKZG9jdW1lbnQud3JpdGUoIlRlc3QgdG9vazogIiAr
IGR1cmF0aW9uICsgIm1zIik7Cjwvc2NyaXB0Pgo=
</data>

          </attachment>
          <attachment
              isobsolete="0"
              ispatch="0"
              isprivate="0"
          >
            <attachid>21325</attachid>
            <date>2008-05-23 20:25:31 -0700</date>
            <delta_ts>2008-05-23 20:25:31 -0700</delta_ts>
            <desc>better version of Darin&apos;s extended version</desc>
            <filename>test26-profile.html</filename>
            <type>text/html</type>
            <size>3722</size>
            <attacher name="Maciej Stachowiak">mjs</attacher>
            
              <data encoding="base64">PGRpdiBjbGFzcz0iYnVja2V0cyIKICAgPjxwIGlkPSJidWNrZXQxIiBjbGFzcz0ieiI+PC9wCiAg
ID48cCBpZD0iYnVja2V0MiIgY2xhc3M9InoiPjwvcAogICA+PHAgaWQ9ImJ1Y2tldDMiIGNsYXNz
PSJ6Ij48L3AKICAgPjxwIGlkPSJidWNrZXQ0IiBjbGFzcz0ieiI+PC9wCiAgID48cCBpZD0iYnVj
a2V0NSIgY2xhc3M9InoiPjwvcAogICA+PHAgaWQ9ImJ1Y2tldDYiIGNsYXNzPSJ6Ij48L3A+CiAg
PC9kaXY+CjxzY3JpcHQ+CmlmICh3aW5kb3cubGF5b3V0VGVzdENvbnRyb2xsZXIpIHsKICAgIGxh
eW91dFRlc3RDb250cm9sbGVyLmR1bXBBc1RleHQoKTsKfQo8L3NjcmlwdD4KPHNjcmlwdD4KdmFy
IHN0YXJ0ID0gbmV3IERhdGUoKTsKCiAgZnVuY3Rpb24gZmFpbChtZXNzYWdlKSB7CiAgICAgIGRv
Y3VtZW50LndyaXRlKG1lc3NhZ2UgKyAiPGJyPiIpOwogIH0KICBmdW5jdGlvbiBhc3NlcnQoY29u
ZGl0aW9uLCBtZXNzYWdlKSB7CiAgICBpZiAoIWNvbmRpdGlvbikKICAgICAgZmFpbChtZXNzYWdl
KTsKICB9CiAgZnVuY3Rpb24gYXNzZXJ0RXF1YWxzKGV4cHJlc3Npb24sIHZhbHVlLCBtZXNzYWdl
KSB7CiAgICBpZiAoZXhwcmVzc2lvbiAhPSB2YWx1ZSkgewogICAgICBleHByZXNzaW9uID0gKCIi
K2V4cHJlc3Npb24pLnJlcGxhY2UoL1tcclxuXSsvZywgIlxcbiIpOwogICAgICB2YWx1ZSA9ICgi
Iit2YWx1ZSkucmVwbGFjZSgvXHI/XG4vZywgIlxcbiIpOwogICAgICBmYWlsKCJleHBlY3RlZDog
IiArIHZhbHVlICsgIiwgZ290OiAiICsgZXhwcmVzc2lvbiArICIgLSAiICsgbWVzc2FnZSk7CiAg
ICB9CiAgfQoKICB2YXIga3VuZ0Z1RGVhdGhHcmlwID0gbnVsbDsgLy8gdXNlZCB0byBob2xkIHRo
aW5ncyBmcm9tIHRlc3QgdG8gdGVzdAoKZnVuY3Rpb24gdGVzdDI2KCkgewogICAgICAvLyB0ZXN0
IDI2OiBjaGVjayB0aGF0IGRvY3VtZW50IHRyZWUgc3Vydml2ZXMgd2hpbGUgc3RpbGwgYWNjZXNz
aWJsZQogICAgICB2YXIgZDsKICAgICAgLy8gZTEgLSBhbiBlbGVtZW50IHRoYXQncyBpbiBhIGRv
Y3VtZW50CiAgICAgIGQgPSBkb2N1bWVudC5pbXBsZW1lbnRhdGlvbi5jcmVhdGVEb2N1bWVudChu
dWxsLCBudWxsLCBudWxsKTsKICAgICAgdmFyIGUxID0gZC5jcmVhdGVFbGVtZW50KCd0ZXN0Jyk7
CiAgICAgIGQuYXBwZW5kQ2hpbGQoZC5jcmVhdGVFbGVtZW50KCdyb290JykpOwogICAgICBkLmRv
Y3VtZW50RWxlbWVudC5hcHBlbmRDaGlsZChlMSk7CiAgICAgIGFzc2VydChlMS5wYXJlbnROb2Rl
LCAiZTEgLSBwYXJlbnQgZWxlbWVudCBkb2Vzbid0IGV4aXN0Iik7CiAgICAgIGFzc2VydChlMS5w
YXJlbnROb2RlLm93bmVyRG9jdW1lbnQsICJlMSAtIGRvY3VtZW50IGRvZXNuJ3QgZXhpc3QiKTsK
ICAgICAgLy8gZTIgLSBhbiBlbGVtZW50IHRoYXQncyBub3QgaW4gYSBkb2N1bWVudAogICAgICBk
ID0gZG9jdW1lbnQuaW1wbGVtZW50YXRpb24uY3JlYXRlRG9jdW1lbnQobnVsbCwgbnVsbCwgbnVs
bCk7CiAgICAgIHZhciBlMiA9IGQuY3JlYXRlRWxlbWVudCgndGVzdCcpOwogICAgICBkLmNyZWF0
ZUVsZW1lbnQoJ3Jvb3QnKS5hcHBlbmRDaGlsZChlMik7CiAgICAgIGFzc2VydChlMi5wYXJlbnRO
b2RlLCAiZTIgLSBwYXJlbnQgZWxlbWVudCBkb2Vzbid0IGV4aXN0Iik7CiAgICAgIGFzc2VydChl
Mi5wYXJlbnROb2RlLm93bmVyRG9jdW1lbnQsICJlMiAtIGRvY3VtZW50IGRvZXNuJ3QgZXhpc3Qi
KTsKICAgICAgLy8gbm93IHRyeSB0byBkZWNvdXBsZSB0aGVtCiAgICAgIGQgPSBudWxsOwogICAg
ICBrdW5nRnVEZWF0aEdyaXAgPSBbZTEsIGUyXTsKICAgICAgYXNzZXJ0KGUxLnBhcmVudE5vZGUs
ICJlMSAtIHBhcmVudCBlbGVtZW50IGRvZXNuJ3QgZXhpc3QgYWZ0ZXIgZHJvcHBpbmcgcmVmZXJl
bmNlIHRvIGRvY3VtZW50Iik7CiAgICAgIGFzc2VydChlMS5wYXJlbnROb2RlLm93bmVyRG9jdW1l
bnQsICJlMSAtIGRvY3VtZW50IGRvZXNuJ3QgZXhpc3QgYWZ0ZXIgZHJvcHBpbmcgcmVmZXJlbmNl
IHRvIGRvY3VtZW50Iik7CiAgICAgIGFzc2VydChlMi5wYXJlbnROb2RlLCAiZTIgLSBwYXJlbnQg
ZWxlbWVudCBkb2Vzbid0IGV4aXN0IGFmdGVyIGRyb3BwaW5nIHJlZmVyZW5jZSB0byBkb2N1bWVu
dCIpOwogICAgICBhc3NlcnQoZTIucGFyZW50Tm9kZS5vd25lckRvY3VtZW50LCAiZTIgLSBkb2N1
bWVudCBkb2Vzbid0IGV4aXN0IGFmdGVyIGRyb3BwaW5nIHJlZmVyZW5jZSB0byBkb2N1bWVudCIp
OwogICAgICB2YXIgbG9vcHMgPSA1MDAwMDsKICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsb29w
czsgaSArPSAxKSB7CiAgICAgICAgLy8gd2Ugd2FudCB0byBmb3JjZSBhIEdDIGhlcmUsIHNvIHdl
IHVzZSB1cCBsb3RzIG9mIG1lbW9yeQogICAgICAgIC8vIHdlIHRha2UgdGhlIG9wcG9ydHVuaXR5
IHRvIHNuZWFrIGluIGEgcGVyZiB0ZXN0IHRvIG1ha2UgRE9NIGFuZCBKUyBzdHVmZiBmYXN0ZXIu
Li4KICAgICAgICBkID0gbmV3IERhdGUoKTsKICAgICAgICBkID0gbmV3IChmdW5jdGlvbiAoeCkg
eyByZXR1cm4geyB0b1N0cmluZzogZnVuY3Rpb24gKCkgeyByZXR1cm4geC50b1N0cmluZygpIH0g
fSB9KShkLnZhbHVlT2YoKSk7CiAgICAgICAgZCA9IGRvY3VtZW50LmNyZWF0ZVRleHROb2RlKCJp
dGVyYXRpb24gIiArIGkgKyAiIGF0ICIgKyBkKTsKICAgICAgICBkb2N1bWVudC5jcmVhdGVFbGVt
ZW50KCdhJykuYXBwZW5kQ2hpbGQoZCk7CiAgICAgICAgZCA9IGQucGFyZW50Tm9kZTsKICAgICAg
ICBkb2N1bWVudC5ib2R5Lmluc2VydEJlZm9yZShkLCBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgn
YnVja2V0MScpLnBhcmVudE5vZGUpOwogICAgICAgIGFzc2VydChkb2N1bWVudC5nZXRFbGVtZW50
QnlJZCgnYnVja2V0MicpLm5leHRTaWJsaW5nLnBhcmVudE5vZGUucHJldmlvdXNTaWJsaW5nLmZp
cnN0Q2hpbGQuZGF0YS5tYXRjaCgvQVRcVy9pKSwgIml0ZXJhdGlvbiAiICsgaSArICIgZmFpbGVk
Iik7CiAgICAgICAgZC5zZXRBdHRyaWJ1dGUoJ2NsYXNzJywgZC50ZXh0Q29udGVudCk7CiAgICAg
ICAgZG9jdW1lbnQuYm9keS5yZW1vdmVDaGlsZChkKTsKICAgICAgfQogICAgICBhc3NlcnQoZTEu
cGFyZW50Tm9kZSwgImUxIC0gcGFyZW50IGVsZW1lbnQgZG9lc24ndCBleGlzdCBhZnRlciBsb29w
aW5nIik7CiAgICAgIGFzc2VydChlMS5wYXJlbnROb2RlLm93bmVyRG9jdW1lbnQsICJlMSAtIGRv
Y3VtZW50IGRvZXNuJ3QgZXhpc3QgYWZ0ZXIgbG9vcGluZyIpOwogICAgICBhc3NlcnRFcXVhbHMo
ZTEucGFyZW50Tm9kZS5vd25lckRvY3VtZW50Lm5vZGVUeXBlLCA5LCAiZTEgLSBkb2N1bWVudCBu
b2RlIHR5cGUgaGFzIHdyb25nIG5vZGUgdHlwZSIpOwogICAgICBhc3NlcnQoZTIucGFyZW50Tm9k
ZSwgImUyIC0gcGFyZW50IGVsZW1lbnQgZG9lc24ndCBleGlzdCBhZnRlciBsb29waW5nIik7CiAg
ICAgIGFzc2VydChlMi5wYXJlbnROb2RlLm93bmVyRG9jdW1lbnQsICJlMiAtIGRvY3VtZW50IGRv
ZXNuJ3QgZXhpc3QgYWZ0ZXIgbG9vcGluZyIpOwogICAgICBhc3NlcnRFcXVhbHMoZTIucGFyZW50
Tm9kZS5vd25lckRvY3VtZW50Lm5vZGVUeXBlLCA5LCAiZTIgLSBkb2N1bWVudCBub2RlIHR5cGUg
aGFzIHdyb25nIG5vZGUgdHlwZSIpOwp9Cgp0ZXN0MjYoKTsKCnZhciBkdXJhdGlvbiA9IG5ldyBE
YXRlKCkgLSBzdGFydDsKZG9jdW1lbnQud3JpdGUoIlRlc3QgdG9vazogIiArIGR1cmF0aW9uICsg
Im1zIik7Cjwvc2NyaXB0Pgo=
</data>

          </attachment>
          <attachment
              isobsolete="1"
              ispatch="1"
              isprivate="0"
          >
            <attachid>21344</attachid>
            <date>2008-05-25 19:48:32 -0700</date>
            <delta_ts>2008-05-26 23:01:36 -0700</delta_ts>
            <desc>not quite working version of optimizing &quot;document&quot; to a static slot</desc>
            <filename>static-doc-slot.patch.txt</filename>
            <type>text/plain</type>
            <size>5331</size>
            <attacher name="Maciej Stachowiak">mjs</attacher>
            
              <data encoding="base64">SW5kZXg6IEphdmFTY3JpcHRDb3JlL0NoYW5nZUxvZwo9PT09PT09PT09PT09PT09PT09PT09PT09
PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09Ci0tLSBKYXZhU2NyaXB0
Q29yZS9DaGFuZ2VMb2cJKHJldmlzaW9uIDM0MTI3KQorKysgSmF2YVNjcmlwdENvcmUvQ2hhbmdl
TG9nCSh3b3JraW5nIGNvcHkpCkBAIC0xLDMgKzEsMTIgQEAKKzIwMDgtMDUtMjUgIE1hY2llaiBT
dGFjaG93aWFrICA8bWpzQGFwcGxlLmNvbT4KKworICAgICAgICBSZXZpZXdlZCBieSBOT0JPRFkg
KE9PUFMhKS4KKyAgICAgICAgCisgICAgICAgIC0gbWFrZSBhZGRTdGF0aWNHbG9iYWxzIHByb3Rl
Y3RlZCBpbnN0ZWFkIG9mIHByaXZhdGUgc28gc3ViY2xhc3NlcyBjYW4gdXNlIGl0CisKKyAgICAg
ICAgKiBKYXZhU2NyaXB0Q29yZS5leHA6CisgICAgICAgICoga2pzL0pTR2xvYmFsT2JqZWN0Lmg6
CisKIDIwMDgtMDUtMjUgIEFsZXhleSBQcm9za3VyeWFrb3YgIDxhcEB3ZWJraXQub3JnPgogCiAg
ICAgICAgIEZpeGluZyBhIHR5cG8gaW4gdGhlIHByZXZpb3VzIGNvbW1pdCBtYWRlIGFzIGEgbGFz
dCBtaW51dGUgY2hhbmdlLgpJbmRleDogSmF2YVNjcmlwdENvcmUvSmF2YVNjcmlwdENvcmUuZXhw
Cj09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09
PT09PT09PT09PT0KLS0tIEphdmFTY3JpcHRDb3JlL0phdmFTY3JpcHRDb3JlLmV4cAkocmV2aXNp
b24gMzQxMjcpCisrKyBKYXZhU2NyaXB0Q29yZS9KYXZhU2NyaXB0Q29yZS5leHAJKHdvcmtpbmcg
Y29weSkKQEAgLTEwOSw2ICsxMDksNyBAQCBfX1pOM0tKUzExUHJvcGVydHlNYXA1Y2xlYXJFdgog
X19aTjNLSlMxMVByb3BlcnR5TWFwRDFFdgogX19aTjNLSlMxMkRhdGVJbnN0YW5jZTRpbmZvRQog
X19aTjNLSlMxMlByb3BlcnR5U2xvdDE1dW5kZWZpbmVkR2V0dGVyRVBOU185RXhlY1N0YXRlRVBO
U184SlNPYmplY3RFUktOU18xMElkZW50aWZpZXJFUktTMF8KK19fWk4zS0pTMTJSZWdpc3RlckZp
bGUxNGFkZEdsb2JhbFNsb3RzRW0KIF9fWk4zS0pTMTNBcnJheUluc3RhbmNlNGluZm9FCiBfX1pO
M0tKUzEzQ29kZUdlbmVyYXRvcjIxc2V0RHVtcHNHZW5lcmF0ZWRDb2RlRWIKIF9fWk4zS0pTMTNT
dGF0ZW1lbnROb2RlNnNldExvY0VpaQpJbmRleDogSmF2YVNjcmlwdENvcmUva2pzL0pTR2xvYmFs
T2JqZWN0LmgKPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09
PT09PT09PT09PT09PT09PT09PQotLS0gSmF2YVNjcmlwdENvcmUva2pzL0pTR2xvYmFsT2JqZWN0
LmgJKHJldmlzaW9uIDM0MTI3KQorKysgSmF2YVNjcmlwdENvcmUva2pzL0pTR2xvYmFsT2JqZWN0
LmgJKHdvcmtpbmcgY29weSkKQEAgLTI2NCw3ICsyNjQsNyBAQCBuYW1lc3BhY2UgS0pTIHsKICAg
ICAgICAgLy8gSW5pdGlhbGl6ZSBhbmQvb3IgcmV0cmlldmUgcGVyLXRocmVhZCBoYXNoIHRhYmxl
cyAtIHVzZSBwZXJUaHJlYWREYXRhKCkgZm9yIGZhc3RlciBhY2Nlc3MgaW5zdGVhZC4KICAgICAg
ICAgc3RhdGljIFRocmVhZENsYXNzSW5mb0hhc2hUYWJsZXMqIHRocmVhZENsYXNzSW5mb0hhc2hU
YWJsZXMoKTsKIAotICAgIHByaXZhdGU6CisgICAgcHJvdGVjdGVkOgogICAgICAgICB2b2lkIGlu
aXQoSlNPYmplY3QqIHRoaXNWYWx1ZSk7CiAgICAgICAgIAogICAgICAgICBKU0dsb2JhbE9iamVj
dERhdGEqIGQoKSBjb25zdCB7IHJldHVybiBzdGF0aWNfY2FzdDxKU0dsb2JhbE9iamVjdERhdGEq
PihKU1ZhcmlhYmxlT2JqZWN0OjpkKTsgfQpAQCAtMjgzLDYgKzI4Myw3IEBAIG5hbWVzcGFjZSBL
SlMgewogICAgICAgICB9OwogICAgICAgICB2b2lkIGFkZFN0YXRpY0dsb2JhbHMoR2xvYmFsUHJv
cGVydHlJbmZvKiwgaW50IGNvdW50KTsKIAorICAgIHByaXZhdGU6CiAgICAgICAgIGJvb2wgY2hl
Y2tUaW1lb3V0KCk7CiAgICAgICAgIHZvaWQgcmVzZXRUaW1lb3V0Q2hlY2soKTsKIApJbmRleDog
V2ViQ29yZS9DaGFuZ2VMb2cKPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09
PT09PT09PT09PT09PT09PT09PT09PT09PT09PQotLS0gV2ViQ29yZS9DaGFuZ2VMb2cJKHJldmlz
aW9uIDM0MTI4KQorKysgV2ViQ29yZS9DaGFuZ2VMb2cJKHdvcmtpbmcgY29weSkKQEAgLTEsMyAr
MSwyMCBAQAorMjAwOC0wNS0yNSAgTWFjaWVqIFN0YWNob3dpYWsgIDxtanNAYXBwbGUuY29tPgor
CisgICAgICAgIFJldmlld2VkIGJ5IE5PQk9EWSAoT09QUyEpLgorCisgICAgICAgIC0gYmluZCB0
aGUgd2luZG93J3MgImRvY3VtZW50IiBhbmQgIndpbmRvdyIgcHJvcGVydGllcyB0byBzdGF0aWMg
c2xvdHMKKyAgICAgICAgMC44JSBzcGVlZHVwIG9uIEFjaWQzIHRlc3QgMjYKKyAgICAgICAgCisg
ICAgICAgIE9ubHkgdGhlICJkb2N1bWVudCIgcGFydCBtYXR0ZXJzIGZvciBBY2lkMywgYnV0IHNp
bmNlIEkgd2FzIGRvaW5nCisgICAgICAgIHRoaXMgYW55d2F5LCAid2luZG93IiBhbHNvIHNlZW1l
ZCBsaWtlIGEgZ29vZCBvbmUgdG8gb3B0aW1pemUuCisKKyAgICAgICAgKiBiaW5kaW5ncy9qcy9K
U0RPTVdpbmRvd0Jhc2UuY3BwOgorICAgICAgICAoV2ViQ29yZTo6SlNET01XaW5kb3dCYXNlOjpp
bml0R2xvYmFscyk6CisgICAgICAgICogYmluZGluZ3MvanMvSlNET01XaW5kb3dCYXNlLmg6Cisg
ICAgICAgICogYmluZGluZ3MvanMva2pzX3Byb3h5LmNwcDoKKyAgICAgICAgKFdlYkNvcmU6OktK
U1Byb3h5Ojppbml0U2NyaXB0KToKKyAgICAgICAgKFdlYkNvcmU6OktKU1Byb3h5OjpjbGVhckRv
Y3VtZW50V3JhcHBlcik6CisKIDIwMDgtMDUtMjUgIE1hY2llaiBTdGFjaG93aWFrICA8bWpzQGFw
cGxlLmNvbT4KIAogICAgICAgICBSZXZpZXdlZCBieSBEYXJpbi4KSW5kZXg6IFdlYkNvcmUvYmlu
ZGluZ3MvanMvSlNET01XaW5kb3dCYXNlLmNwcAo9PT09PT09PT09PT09PT09PT09PT09PT09PT09
PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09Ci0tLSBXZWJDb3JlL2JpbmRp
bmdzL2pzL0pTRE9NV2luZG93QmFzZS5jcHAJKHJldmlzaW9uIDM0MTI3KQorKysgV2ViQ29yZS9i
aW5kaW5ncy9qcy9KU0RPTVdpbmRvd0Jhc2UuY3BwCSh3b3JraW5nIGNvcHkpCkBAIC0xODYsNiAr
MTg2LDIzIEBAIEpTRE9NV2luZG93QmFzZTo6SlNET01XaW5kb3dCYXNlKEpTT2JqZWMKICAgICBz
ZXRUaW1lb3V0VGltZSgxMDAwMCk7CiB9CiAKK3ZvaWQgSlNET01XaW5kb3dCYXNlOjppbml0R2xv
YmFscygpCit7CisgICAgQVNTRVJUKG1faW1wbC0+ZG9jdW1lbnQoKSk7CisKKyAgICBSZWdpc3Rl
ckZpbGUqIHJlZ2lzdGVyRmlsZSA9IHJlZ2lzdGVyRmlsZVN0YWNrKCkuY3VycmVudCgpOworICAg
IGlmICghcmVnaXN0ZXJGaWxlLT5zYWZlRm9yUmVlbnRyeSgpIHx8ICFyZWdpc3RlckZpbGUtPmlz
R2xvYmFsKCkpCisgICAgICAgIHJldHVybjsKKworICAgIEV4ZWNTdGF0ZSogZXhlYyA9IGdsb2Jh
bEV4ZWMoKTsKKyAgICBHbG9iYWxQcm9wZXJ0eUluZm8gc3RhdGljR2xvYmFsc1tdID0geworICAg
ICAgICBHbG9iYWxQcm9wZXJ0eUluZm8oImRvY3VtZW50IiwgdG9KUyhleGVjLCBtX2ltcGwtPmRv
Y3VtZW50KCkpLCBEb250RGVsZXRlIHwgUmVhZE9ubHkpLAorICAgICAgICBHbG9iYWxQcm9wZXJ0
eUluZm8oIndpbmRvdyIsIGQtPm1fc2hlbGwsIERvbnREZWxldGUgfCBSZWFkT25seSkKKyAgICB9
OworICAgIAorICAgIGFkZFN0YXRpY0dsb2JhbHMoc3RhdGljR2xvYmFscywgc2l6ZW9mKHN0YXRp
Y0dsb2JhbHMpIC8gc2l6ZW9mKEdsb2JhbFByb3BlcnR5SW5mbykpOworfQorCiBKU0RPTVdpbmRv
d0Jhc2U6On5KU0RPTVdpbmRvd0Jhc2UoKQogewogICAgIGNsZWFyQWxsVGltZW91dHMoKTsKSW5k
ZXg6IFdlYkNvcmUvYmluZGluZ3MvanMvSlNET01XaW5kb3dCYXNlLmgKPT09PT09PT09PT09PT09
PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQotLS0g
V2ViQ29yZS9iaW5kaW5ncy9qcy9KU0RPTVdpbmRvd0Jhc2UuaAkocmV2aXNpb24gMzQxMjcpCisr
KyBXZWJDb3JlL2JpbmRpbmdzL2pzL0pTRE9NV2luZG93QmFzZS5oCSh3b3JraW5nIGNvcHkpCkBA
IC01NCw2ICs1NCw4IEBAIG5hbWVzcGFjZSBXZWJDb3JlIHsKICAgICBwdWJsaWM6CiAgICAgICAg
IHZpcnR1YWwgfkpTRE9NV2luZG93QmFzZSgpOwogCisgICAgICAgIHZvaWQgaW5pdEdsb2JhbHMo
KTsKKwogICAgICAgICBET01XaW5kb3cqIGltcGwoKSBjb25zdCB7IHJldHVybiBtX2ltcGwuZ2V0
KCk7IH0KIAogICAgICAgICB2b2lkIGRpc2Nvbm5lY3RGcmFtZSgpOwpJbmRleDogV2ViQ29yZS9i
aW5kaW5ncy9qcy9ranNfcHJveHkuY3BwCj09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09
PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KLS0tIFdlYkNvcmUvYmluZGluZ3Mv
anMva2pzX3Byb3h5LmNwcAkocmV2aXNpb24gMzQxMjcpCisrKyBXZWJDb3JlL2JpbmRpbmdzL2pz
L2tqc19wcm94eS5jcHAJKHdvcmtpbmcgY29weSkKQEAgLTE1NSw2ICsxNTUsNyBAQCB2b2lkIEtK
U1Byb3h5Ojppbml0U2NyaXB0KCkKICAgICBKU0xvY2sgbG9jazsKIAogICAgIG1fd2luZG93U2hl
bGwgPSBuZXcgSlNET01XaW5kb3dTaGVsbChtX2ZyYW1lLT5kb21XaW5kb3coKSk7CisgICAgbV93
aW5kb3dTaGVsbC0+d2luZG93KCktPmluaXRHbG9iYWxzKCk7CiAKICAgICBpZiAoUGFnZSogcGFn
ZSA9IG1fZnJhbWUtPnBhZ2UoKSkgewogICAgICAgICBhdHRhY2hEZWJ1Z2dlcihwYWdlLT5kZWJ1
Z2dlcigpKTsKSW5kZXg6IFdlYkNvcmUvcGFnZS9GcmFtZS5jcHAKPT09PT09PT09PT09PT09PT09
PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQotLS0gV2Vi
Q29yZS9wYWdlL0ZyYW1lLmNwcAkocmV2aXNpb24gMzQxMjcpCisrKyBXZWJDb3JlL3BhZ2UvRnJh
bWUuY3BwCSh3b3JraW5nIGNvcHkpCkBAIC0yNjAsNiArMjYwLDEwIEBAIHZvaWQgRnJhbWU6OnNl
dERvY3VtZW50KFBhc3NSZWZQdHI8RG9jdW0KIAogICAgIC8vIFJlbW92ZSB0aGUgY2FjaGVkICdk
b2N1bWVudCcgcHJvcGVydHksIHdoaWNoIGlzIG5vdyBzdGFsZS4KICAgICBkLT5tX2pzY3JpcHQu
Y2xlYXJEb2N1bWVudFdyYXBwZXIoKTsKKyAgICBpZiAoZC0+bV9kb2MgJiYgZC0+bV9qc2NyaXB0
LmhhdmVXaW5kb3dTaGVsbCgpKSB7CisgICAgICAgIEpTTG9jayBsb2NrOworICAgICAgICBkLT5t
X2pzY3JpcHQuZ2xvYmFsT2JqZWN0KCktPmluaXRHbG9iYWxzKCk7CisgICAgfQogfQogCiBTZXR0
aW5ncyogRnJhbWU6OnNldHRpbmdzKCkgY29uc3QK
</data>

          </attachment>
      

    </bug>

</bugzilla>