<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" /><style type="text/css"><!--
#msg dl { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fc0 solid; padding: 6px; }
#msg ul, pre { overflow: auto; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<title>[20748] branches/js-collector-tweaks/JavaScriptCore</title>
</head>
<body>

<div id="msg">
<dl>
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/20748">20748</a></dd>
<dt>Author</dt> <dd>mjs</dd>
<dt>Date</dt> <dd>2007-04-06 03:26:27 -0700 (Fri, 06 Apr 2007)</dd>
</dl>

<h3>Log Message</h3>
<pre>        Not reviewed, experimental change.
        
        - shrink PropertyMap by 8 bytes and therefore shrink CELL_SIZE to 40 (for 32-bit; 
        similar shrinkage for 64-bit)

        Inspired by similar changes by Christopher E. Hyde &lt;C.Hyde@parableuk.force9.co.uk&gt;
        done in the kjs-tweaks branch of KDE's kjs. However, this version is somewhat 
        cleaner style-wise and avoids some of the negative speed impact (at least on gcc/x86) 
        of his version.
        
        This is nearly a wash performance-wise, maybe a slight slowdown, but worth doing
        to eventually reach cell size 32.
        
        * kjs/collector.cpp:
        (KJS::):
        * kjs/property_map.cpp:
        (KJS::PropertyMap::~PropertyMap):
        (KJS::PropertyMap::clear):
        (KJS::PropertyMap::get):
        (KJS::PropertyMap::getLocation):
        (KJS::PropertyMap::put):
        (KJS::PropertyMap::insert):
        (KJS::PropertyMap::expand):
        (KJS::PropertyMap::rehash):
        (KJS::PropertyMap::remove):
        (KJS::PropertyMap::mark):
        (KJS::PropertyMap::containsGettersOrSetters):
        (KJS::PropertyMap::getEnumerablePropertyNames):
        (KJS::PropertyMap::getSparseArrayPropertyNames):
        (KJS::PropertyMap::save):
        (KJS::PropertyMap::checkConsistency):
        * kjs/property_map.h:
        (KJS::PropertyMap::hasGetterSetterProperties):
        (KJS::PropertyMap::setHasGetterSetterProperties):
        (KJS::PropertyMap::):
        (KJS::PropertyMap::PropertyMap):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#branchesjscollectortweaksJavaScriptCoreChangeLog">branches/js-collector-tweaks/JavaScriptCore/ChangeLog</a></li>
<li><a href="#branchesjscollectortweaksJavaScriptCorekjscollectorcpp">branches/js-collector-tweaks/JavaScriptCore/kjs/collector.cpp</a></li>
<li><a href="#branchesjscollectortweaksJavaScriptCorekjsproperty_mapcpp">branches/js-collector-tweaks/JavaScriptCore/kjs/property_map.cpp</a></li>
<li><a href="#branchesjscollectortweaksJavaScriptCorekjsproperty_maph">branches/js-collector-tweaks/JavaScriptCore/kjs/property_map.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="branchesjscollectortweaksJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: branches/js-collector-tweaks/JavaScriptCore/ChangeLog (20747 => 20748)</h4>
<pre class="diff"><span>
<span class="info">--- branches/js-collector-tweaks/JavaScriptCore/ChangeLog        2007-04-06 08:26:13 UTC (rev 20747)
+++ branches/js-collector-tweaks/JavaScriptCore/ChangeLog        2007-04-06 10:26:27 UTC (rev 20748)
</span><span class="lines">@@ -2,6 +2,45 @@
</span><span class="cx"> 
</span><span class="cx">         Not reviewed, experimental change.
</span><span class="cx">         
</span><ins>+        - shrink PropertyMap by 8 bytes and therefore shrink CELL_SIZE to 40 (for 32-bit; 
+        similar shrinkage for 64-bit)
+
+        Inspired by similar changes by Christopher E. Hyde &lt;C.Hyde@parableuk.force9.co.uk&gt;
+        done in the kjs-tweaks branch of KDE's kjs. However, this version is somewhat 
+        cleaner style-wise and avoids some of the negative speed impact (at least on gcc/x86) 
+        of his version.
+        
+        This is nearly a wash performance-wise, maybe a slight slowdown, but worth doing
+        to eventually reach cell size 32.
+        
+        * kjs/collector.cpp:
+        (KJS::):
+        * kjs/property_map.cpp:
+        (KJS::PropertyMap::~PropertyMap):
+        (KJS::PropertyMap::clear):
+        (KJS::PropertyMap::get):
+        (KJS::PropertyMap::getLocation):
+        (KJS::PropertyMap::put):
+        (KJS::PropertyMap::insert):
+        (KJS::PropertyMap::expand):
+        (KJS::PropertyMap::rehash):
+        (KJS::PropertyMap::remove):
+        (KJS::PropertyMap::mark):
+        (KJS::PropertyMap::containsGettersOrSetters):
+        (KJS::PropertyMap::getEnumerablePropertyNames):
+        (KJS::PropertyMap::getSparseArrayPropertyNames):
+        (KJS::PropertyMap::save):
+        (KJS::PropertyMap::checkConsistency):
+        * kjs/property_map.h:
+        (KJS::PropertyMap::hasGetterSetterProperties):
+        (KJS::PropertyMap::setHasGetterSetterProperties):
+        (KJS::PropertyMap::):
+        (KJS::PropertyMap::PropertyMap):
+
+2007-04-06  Maciej Stachowiak  &lt;mjs@apple.com&gt;
+
+        Not reviewed, experimental change.
+        
</ins><span class="cx">         - change blocks to 64k in size, and use various platform-specific calls to allocate at 64k-aligned addresses
</span><span class="cx"> 
</span><span class="cx">         * kjs/collector.cpp:
</span></span></pre></div>
<a id="branchesjscollectortweaksJavaScriptCorekjscollectorcpp"></a>
<div class="modfile"><h4>Modified: branches/js-collector-tweaks/JavaScriptCore/kjs/collector.cpp (20747 => 20748)</h4>
<pre class="diff"><span>
<span class="info">--- branches/js-collector-tweaks/JavaScriptCore/kjs/collector.cpp        2007-04-06 08:26:13 UTC (rev 20747)
+++ branches/js-collector-tweaks/JavaScriptCore/kjs/collector.cpp        2007-04-06 10:26:27 UTC (rev 20748)
</span><span class="lines">@@ -67,8 +67,8 @@
</span><span class="cx"> // tunable parameters
</span><span class="cx"> 
</span><span class="cx"> template&lt;bool is32Bit, bool is64Bit&gt; struct CellSize;
</span><del>-template&lt;&gt; struct CellSize&lt;true, false&gt; { static const size_t m_value = 48; }; // 32-bit
-template&lt;&gt; struct CellSize&lt;false, true&gt; { static const size_t m_value = 80; }; // 64-bit
</del><ins>+template&lt;&gt; struct CellSize&lt;true, false&gt; { static const size_t m_value = 40; }; // 32-bit
+template&lt;&gt; struct CellSize&lt;false, true&gt; { static const size_t m_value = 64; }; // 64-bit
</ins><span class="cx"> 
</span><span class="cx"> const size_t BLOCK_SIZE = (16 * 4096); // 64k
</span><span class="cx"> const size_t SPARE_EMPTY_BLOCKS = 2;
</span></span></pre></div>
<a id="branchesjscollectortweaksJavaScriptCorekjsproperty_mapcpp"></a>
<div class="modfile"><h4>Modified: branches/js-collector-tweaks/JavaScriptCore/kjs/property_map.cpp (20747 => 20748)</h4>
<pre class="diff"><span>
<span class="info">--- branches/js-collector-tweaks/JavaScriptCore/kjs/property_map.cpp        2007-04-06 08:26:13 UTC (rev 20747)
+++ branches/js-collector-tweaks/JavaScriptCore/kjs/property_map.cpp        2007-04-06 10:26:27 UTC (rev 20748)
</span><span class="lines">@@ -39,8 +39,6 @@
</span><span class="cx"> // 2/28/2006 ggaren: super accurate JS iBench says that USE_SINGLE_ENTRY is a
</span><span class="cx"> // 3.2% performance boost.
</span><span class="cx"> 
</span><del>-// FIXME: _singleEntry.index is unused.
-
</del><span class="cx"> #if !DO_CONSISTENCY_CHECK
</span><span class="cx"> #define checkConsistency() ((void)0)
</span><span class="cx"> #endif
</span><span class="lines">@@ -110,17 +108,17 @@
</span><span class="cx"> 
</span><span class="cx"> PropertyMap::~PropertyMap()
</span><span class="cx"> {
</span><del>-    if (!_table) {
</del><ins>+    if (!m_usingTable) {
</ins><span class="cx"> #if USE_SINGLE_ENTRY
</span><del>-        UString::Rep *key = _singleEntry.key;
</del><ins>+        UString::Rep* key = m_singleEntryKey;
</ins><span class="cx">         if (key)
</span><span class="cx">             key-&gt;deref();
</span><span class="cx"> #endif
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    int minimumKeysToProcess = _table-&gt;keyCount + _table-&gt;sentinelCount;
-    Entry *entries = _table-&gt;entries;
</del><ins>+    int minimumKeysToProcess = m_u.table-&gt;keyCount + m_u.table-&gt;sentinelCount;
+    Entry *entries = m_u.table-&gt;entries;
</ins><span class="cx">     for (int i = 0; i &lt; minimumKeysToProcess; i++) {
</span><span class="cx">         UString::Rep *key = entries[i].key;
</span><span class="cx">         if (key) {
</span><span class="lines">@@ -129,24 +127,24 @@
</span><span class="cx">         } else
</span><span class="cx">             ++minimumKeysToProcess;
</span><span class="cx">     }
</span><del>-    fastFree(_table);
</del><ins>+    fastFree(m_u.table);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void PropertyMap::clear()
</span><span class="cx"> {
</span><del>-    if (!_table) {
</del><ins>+    if (!m_usingTable) {
</ins><span class="cx"> #if USE_SINGLE_ENTRY
</span><del>-        UString::Rep *key = _singleEntry.key;
</del><ins>+        UString::Rep* key = m_singleEntryKey;
</ins><span class="cx">         if (key) {
</span><span class="cx">             key-&gt;deref();
</span><del>-            _singleEntry.key = 0;
</del><ins>+            m_singleEntryKey = 0;
</ins><span class="cx">         }
</span><span class="cx"> #endif
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    int size = _table-&gt;size;
-    Entry *entries = _table-&gt;entries;
</del><ins>+    int size = m_u.table-&gt;size;
+    Entry *entries = m_u.table-&gt;entries;
</ins><span class="cx">     for (int i = 0; i &lt; size; i++) {
</span><span class="cx">         UString::Rep *key = entries[i].key;
</span><span class="cx">         if (isValid(key)) {
</span><span class="lines">@@ -155,8 +153,8 @@
</span><span class="cx">             entries[i].value = 0;
</span><span class="cx">         }
</span><span class="cx">     }
</span><del>-    _table-&gt;keyCount = 0;
-    _table-&gt;sentinelCount = 0;
</del><ins>+    m_u.table-&gt;keyCount = 0;
+    m_u.table-&gt;sentinelCount = 0;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> JSValue *PropertyMap::get(const Identifier &amp;name, unsigned &amp;attributes) const
</span><span class="lines">@@ -165,20 +163,20 @@
</span><span class="cx">     
</span><span class="cx">     UString::Rep *rep = name._ustring.rep();
</span><span class="cx">     
</span><del>-    if (!_table) {
</del><ins>+    if (!m_usingTable) {
</ins><span class="cx"> #if USE_SINGLE_ENTRY
</span><del>-        UString::Rep *key = _singleEntry.key;
</del><ins>+        UString::Rep* key = m_singleEntryKey;
</ins><span class="cx">         if (rep == key) {
</span><del>-            attributes = _singleEntry.attributes;
-            return _singleEntry.value;
</del><ins>+            attributes = m_singleEntryAttributes;
+            return m_u.singleEntryValue;
</ins><span class="cx">         }
</span><span class="cx"> #endif
</span><span class="cx">         return 0;
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     unsigned h = rep-&gt;hash();
</span><del>-    int sizeMask = _table-&gt;sizeMask;
-    Entry *entries = _table-&gt;entries;
</del><ins>+    int sizeMask = m_u.table-&gt;sizeMask;
+    Entry *entries = m_u.table-&gt;entries;
</ins><span class="cx">     int i = h &amp; sizeMask;
</span><span class="cx">     int k = 0;
</span><span class="cx"> #if DUMP_STATISTICS
</span><span class="lines">@@ -206,18 +204,18 @@
</span><span class="cx">     
</span><span class="cx">     UString::Rep *rep = name._ustring.rep();
</span><span class="cx"> 
</span><del>-    if (!_table) {
</del><ins>+    if (!m_usingTable) {
</ins><span class="cx"> #if USE_SINGLE_ENTRY
</span><del>-        UString::Rep *key = _singleEntry.key;
</del><ins>+        UString::Rep *key = m_singleEntryKey;
</ins><span class="cx">         if (rep == key)
</span><del>-            return _singleEntry.value;
</del><ins>+            return m_u.singleEntryValue;
</ins><span class="cx"> #endif
</span><span class="cx">         return 0;
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     unsigned h = rep-&gt;hash();
</span><del>-    int sizeMask = _table-&gt;sizeMask;
-    Entry *entries = _table-&gt;entries;
</del><ins>+    int sizeMask = m_u.table-&gt;sizeMask;
+    Entry *entries = m_u.table-&gt;entries;
</ins><span class="cx">     int i = h &amp; sizeMask;
</span><span class="cx">     int k = 0;
</span><span class="cx"> #if DUMP_STATISTICS
</span><span class="lines">@@ -243,18 +241,18 @@
</span><span class="cx">     
</span><span class="cx">     UString::Rep *rep = name._ustring.rep();
</span><span class="cx"> 
</span><del>-    if (!_table) {
</del><ins>+    if (!m_usingTable) {
</ins><span class="cx"> #if USE_SINGLE_ENTRY
</span><del>-        UString::Rep *key = _singleEntry.key;
</del><ins>+        UString::Rep *key = m_singleEntryKey;
</ins><span class="cx">         if (rep == key)
</span><del>-            return &amp;_singleEntry.value;
</del><ins>+            return &amp;m_u.singleEntryValue;
</ins><span class="cx"> #endif
</span><span class="cx">         return 0;
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     unsigned h = rep-&gt;hash();
</span><del>-    int sizeMask = _table-&gt;sizeMask;
-    Entry *entries = _table-&gt;entries;
</del><ins>+    int sizeMask = m_u.table-&gt;sizeMask;
+    Entry *entries = m_u.table-&gt;entries;
</ins><span class="cx">     int i = h &amp; sizeMask;
</span><span class="cx">     int k = 0;
</span><span class="cx"> #if DUMP_STATISTICS
</span><span class="lines">@@ -310,30 +308,30 @@
</span><span class="cx"> #endif
</span><span class="cx">     
</span><span class="cx"> #if USE_SINGLE_ENTRY
</span><del>-    if (!_table) {
-        UString::Rep *key = _singleEntry.key;
</del><ins>+    if (!m_usingTable) {
+        UString::Rep *key = m_singleEntryKey;
</ins><span class="cx">         if (key) {
</span><del>-            if (rep == key &amp;&amp; !(roCheck &amp;&amp; (_singleEntry.attributes &amp; ReadOnly))) {
-                _singleEntry.value = value;
</del><ins>+            if (rep == key &amp;&amp; !(roCheck &amp;&amp; (m_singleEntryAttributes &amp; ReadOnly))) {
+                m_u.singleEntryValue = value;
</ins><span class="cx">                 return;
</span><span class="cx">             }
</span><span class="cx">         } else {
</span><span class="cx">             rep-&gt;ref();
</span><del>-            _singleEntry.key = rep;
-            _singleEntry.value = value;
-            _singleEntry.attributes = static_cast&lt;short&gt;(attributes);
</del><ins>+            m_singleEntryKey = rep;
+            m_u.singleEntryValue = value;
+            m_singleEntryAttributes = static_cast&lt;short&gt;(attributes);
</ins><span class="cx">             checkConsistency();
</span><span class="cx">             return;
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><del>-    if (!_table || _table-&gt;keyCount * 2 &gt;= _table-&gt;size)
</del><ins>+    if (!m_usingTable || m_u.table-&gt;keyCount * 2 &gt;= m_u.table-&gt;size)
</ins><span class="cx">         expand();
</span><span class="cx">     
</span><span class="cx">     unsigned h = rep-&gt;hash();
</span><del>-    int sizeMask = _table-&gt;sizeMask;
-    Entry *entries = _table-&gt;entries;
</del><ins>+    int sizeMask = m_u.table-&gt;sizeMask;
+    Entry *entries = m_u.table-&gt;entries;
</ins><span class="cx">     int i = h &amp; sizeMask;
</span><span class="cx">     int k = 0;
</span><span class="cx">     bool foundDeletedElement = false;
</span><span class="lines">@@ -344,7 +342,7 @@
</span><span class="cx"> #endif
</span><span class="cx">     while (UString::Rep *key = entries[i].key) {
</span><span class="cx">         if (rep == key) {
</span><del>-            if (roCheck &amp;&amp; (_table-&gt;entries[i].attributes &amp; ReadOnly)) 
</del><ins>+            if (roCheck &amp;&amp; (m_u.table-&gt;entries[i].attributes &amp; ReadOnly)) 
</ins><span class="cx">                 return;
</span><span class="cx">             // Put a new value in an existing hash table entry.
</span><span class="cx">             entries[i].value = value;
</span><span class="lines">@@ -367,7 +365,7 @@
</span><span class="cx">     // Use either the deleted element or the 0 at the end of the chain.
</span><span class="cx">     if (foundDeletedElement) {
</span><span class="cx">         i = deletedElementIndex;
</span><del>-        --_table-&gt;sentinelCount;
</del><ins>+        --m_u.table-&gt;sentinelCount;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     // Create a new hash table entry.
</span><span class="lines">@@ -375,19 +373,19 @@
</span><span class="cx">     entries[i].key = rep;
</span><span class="cx">     entries[i].value = value;
</span><span class="cx">     entries[i].attributes = static_cast&lt;short&gt;(attributes);
</span><del>-    entries[i].index = ++_table-&gt;lastIndexUsed;
-    ++_table-&gt;keyCount;
</del><ins>+    entries[i].index = ++m_u.table-&gt;lastIndexUsed;
+    ++m_u.table-&gt;keyCount;
</ins><span class="cx"> 
</span><span class="cx">     checkConsistency();
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void PropertyMap::insert(UString::Rep *key, JSValue *value, int attributes, int index)
</span><span class="cx"> {
</span><del>-    assert(_table);
</del><ins>+    assert(m_u.table);
</ins><span class="cx"> 
</span><span class="cx">     unsigned h = key-&gt;hash();
</span><del>-    int sizeMask = _table-&gt;sizeMask;
-    Entry *entries = _table-&gt;entries;
</del><ins>+    int sizeMask = m_u.table-&gt;sizeMask;
+    Entry *entries = m_u.table-&gt;entries;
</ins><span class="cx">     int i = h &amp; sizeMask;
</span><span class="cx">     int k = 0;
</span><span class="cx"> #if DUMP_STATISTICS
</span><span class="lines">@@ -412,40 +410,45 @@
</span><span class="cx"> 
</span><span class="cx"> void PropertyMap::expand()
</span><span class="cx"> {
</span><del>-    Table *oldTable = _table;
-    int oldTableSize = oldTable ? oldTable-&gt;size : 0;    
</del><ins>+    Table *oldTable = m_u.table;
+    int oldTableSize = m_usingTable ? oldTable-&gt;size : 0;    
</ins><span class="cx">     rehash(oldTableSize ? oldTableSize * 2 : 16);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void PropertyMap::rehash()
</span><span class="cx"> {
</span><del>-    assert(_table);
-    assert(_table-&gt;size);
-    rehash(_table-&gt;size);
</del><ins>+    assert(m_u.table);
+    assert(m_u.table-&gt;size);
+    rehash(m_u.table-&gt;size);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void PropertyMap::rehash(int newTableSize)
</span><span class="cx"> {
</span><span class="cx">     checkConsistency();
</span><ins>+
+#if USE_SINGLE_ENTRY
+    JSValue* oldSingleEntryValue = m_u.singleEntryValue;
+#endif
+
+    Table *oldTable = m_usingTable ? m_u.table : 0;
+    int oldTableSize = m_usingTable ? oldTable-&gt;size : 0;
+    int oldTableKeyCount = m_usingTable ? oldTable-&gt;keyCount : 0;
</ins><span class="cx">     
</span><del>-    Table *oldTable = _table;
-    int oldTableSize = oldTable ? oldTable-&gt;size : 0;
-    int oldTableKeyCount = oldTable ? oldTable-&gt;keyCount : 0;
-    
-    _table = (Table *)fastCalloc(1, sizeof(Table) + (newTableSize - 1) * sizeof(Entry) );
-    _table-&gt;size = newTableSize;
-    _table-&gt;sizeMask = newTableSize - 1;
-    _table-&gt;keyCount = oldTableKeyCount;
</del><ins>+    m_u.table = (Table *)fastCalloc(1, sizeof(Table) + (newTableSize - 1) * sizeof(Entry) );
+    m_u.table-&gt;size = newTableSize;
+    m_u.table-&gt;sizeMask = newTableSize - 1;
+    m_u.table-&gt;keyCount = oldTableKeyCount;
+    m_usingTable = true;
</ins><span class="cx"> 
</span><span class="cx"> #if USE_SINGLE_ENTRY
</span><del>-    UString::Rep *key = _singleEntry.key;
</del><ins>+    UString::Rep* key = m_singleEntryKey;
</ins><span class="cx">     if (key) {
</span><del>-        insert(key, _singleEntry.value, _singleEntry.attributes, 0);
-        _singleEntry.key = 0;
</del><ins>+        insert(key, oldSingleEntryValue, m_singleEntryAttributes, 0);
+        m_singleEntryKey = 0;
</ins><span class="cx">         // update the count, because single entries don't count towards
</span><span class="cx">         // the table key count
</span><del>-        ++_table-&gt;keyCount;
-        assert(_table-&gt;keyCount == 1);
</del><ins>+        ++m_u.table-&gt;keyCount;
+        assert(m_u.table-&gt;keyCount == 1);
</ins><span class="cx">     }
</span><span class="cx"> #endif
</span><span class="cx">     
</span><span class="lines">@@ -459,7 +462,7 @@
</span><span class="cx">             insert(key, entry.value, entry.attributes, index);
</span><span class="cx">         }
</span><span class="cx">     }
</span><del>-    _table-&gt;lastIndexUsed = lastIndexUsed;
</del><ins>+    m_u.table-&gt;lastIndexUsed = lastIndexUsed;
</ins><span class="cx"> 
</span><span class="cx">     fastFree(oldTable);
</span><span class="cx"> 
</span><span class="lines">@@ -476,12 +479,12 @@
</span><span class="cx"> 
</span><span class="cx">     UString::Rep *key;
</span><span class="cx"> 
</span><del>-    if (!_table) {
</del><ins>+    if (!m_usingTable) {
</ins><span class="cx"> #if USE_SINGLE_ENTRY
</span><del>-        key = _singleEntry.key;
</del><ins>+        key = m_singleEntryKey;
</ins><span class="cx">         if (rep == key) {
</span><span class="cx">             key-&gt;deref();
</span><del>-            _singleEntry.key = 0;
</del><ins>+            m_singleEntryKey = 0;
</ins><span class="cx">             checkConsistency();
</span><span class="cx">         }
</span><span class="cx"> #endif
</span><span class="lines">@@ -490,8 +493,8 @@
</span><span class="cx"> 
</span><span class="cx">     // Find the thing to remove.
</span><span class="cx">     unsigned h = rep-&gt;hash();
</span><del>-    int sizeMask = _table-&gt;sizeMask;
-    Entry *entries = _table-&gt;entries;
</del><ins>+    int sizeMask = m_u.table-&gt;sizeMask;
+    Entry *entries = m_u.table-&gt;entries;
</ins><span class="cx">     int i = h &amp; sizeMask;
</span><span class="cx">     int k = 0;
</span><span class="cx"> #if DUMP_STATISTICS
</span><span class="lines">@@ -519,11 +522,11 @@
</span><span class="cx">     entries[i].key = key;
</span><span class="cx">     entries[i].value = 0;
</span><span class="cx">     entries[i].attributes = DontEnum;
</span><del>-    assert(_table-&gt;keyCount &gt;= 1);
-    --_table-&gt;keyCount;
-    ++_table-&gt;sentinelCount;
</del><ins>+    assert(m_u.table-&gt;keyCount &gt;= 1);
+    --m_u.table-&gt;keyCount;
+    ++m_u.table-&gt;sentinelCount;
</ins><span class="cx">     
</span><del>-    if (_table-&gt;sentinelCount * 4 &gt;= _table-&gt;size)
</del><ins>+    if (m_u.table-&gt;sentinelCount * 4 &gt;= m_u.table-&gt;size)
</ins><span class="cx">         rehash();
</span><span class="cx"> 
</span><span class="cx">     checkConsistency();
</span><span class="lines">@@ -531,10 +534,10 @@
</span><span class="cx"> 
</span><span class="cx"> void PropertyMap::mark() const
</span><span class="cx"> {
</span><del>-    if (!_table) {
</del><ins>+    if (!m_usingTable) {
</ins><span class="cx"> #if USE_SINGLE_ENTRY
</span><del>-        if (_singleEntry.key) {
-            JSValue *v = _singleEntry.value;
</del><ins>+        if (m_singleEntryKey) {
+            JSValue* v = m_u.singleEntryValue;
</ins><span class="cx">             if (!v-&gt;marked())
</span><span class="cx">                 v-&gt;mark();
</span><span class="cx">         }
</span><span class="lines">@@ -542,8 +545,8 @@
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    int minimumKeysToProcess = _table-&gt;keyCount;
-    Entry *entries = _table-&gt;entries;
</del><ins>+    int minimumKeysToProcess = m_u.table-&gt;keyCount;
+    Entry *entries = m_u.table-&gt;entries;
</ins><span class="cx">     for (int i = 0; i &lt; minimumKeysToProcess; i++) {
</span><span class="cx">         JSValue *v = entries[i].value;
</span><span class="cx">         if (v) {
</span><span class="lines">@@ -568,16 +571,16 @@
</span><span class="cx"> 
</span><span class="cx"> bool PropertyMap::containsGettersOrSetters() const
</span><span class="cx"> {
</span><del>-    if (!_table) {
</del><ins>+    if (!m_usingTable) {
</ins><span class="cx"> #if USE_SINGLE_ENTRY
</span><del>-        return !!(_singleEntry.attributes &amp; GetterSetter);
</del><ins>+        return !!(m_singleEntryAttributes &amp; GetterSetter);
</ins><span class="cx"> #else
</span><span class="cx">         return false;
</span><span class="cx"> #endif
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    for (int i = 0; i != _table-&gt;size; ++i) {
-        if (_table-&gt;entries[i].attributes &amp; GetterSetter)
</del><ins>+    for (int i = 0; i != m_u.table-&gt;size; ++i) {
+        if (m_u.table-&gt;entries[i].attributes &amp; GetterSetter)
</ins><span class="cx">             return true;
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="lines">@@ -586,22 +589,22 @@
</span><span class="cx"> 
</span><span class="cx"> void PropertyMap::getEnumerablePropertyNames(PropertyNameArray&amp; propertyNames) const
</span><span class="cx"> {
</span><del>-    if (!_table) {
</del><ins>+    if (!m_usingTable) {
</ins><span class="cx"> #if USE_SINGLE_ENTRY
</span><del>-        UString::Rep *key = _singleEntry.key;
-        if (key &amp;&amp; !(_singleEntry.attributes &amp; DontEnum))
</del><ins>+        UString::Rep* key = m_singleEntryKey;
+        if (key &amp;&amp; !(m_singleEntryAttributes &amp; DontEnum))
</ins><span class="cx">             propertyNames.add(Identifier(key));
</span><span class="cx"> #endif
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     // Allocate a buffer to use to sort the keys.
</span><del>-    Vector&lt;Entry*, smallMapThreshold&gt; sortedEnumerables(_table-&gt;keyCount);
</del><ins>+    Vector&lt;Entry*, smallMapThreshold&gt; sortedEnumerables(m_u.table-&gt;keyCount);
</ins><span class="cx"> 
</span><span class="cx">     // Get pointers to the enumerable entries in the buffer.
</span><span class="cx">     Entry** p = sortedEnumerables.data();
</span><del>-    int size = _table-&gt;size;
-    Entry* entries = _table-&gt;entries;
</del><ins>+    int size = m_u.table-&gt;size;
+    Entry* entries = m_u.table-&gt;entries;
</ins><span class="cx">     for (int i = 0; i != size; ++i) {
</span><span class="cx">         Entry* e = &amp;entries[i];
</span><span class="cx">         if (e-&gt;key &amp;&amp; !(e-&gt;attributes &amp; DontEnum))
</span><span class="lines">@@ -618,9 +621,9 @@
</span><span class="cx"> 
</span><span class="cx"> void PropertyMap::getSparseArrayPropertyNames(PropertyNameArray&amp; propertyNames) const
</span><span class="cx"> {
</span><del>-    if (!_table) {
</del><ins>+    if (!m_usingTable) {
</ins><span class="cx"> #if USE_SINGLE_ENTRY
</span><del>-        UString::Rep *key = _singleEntry.key;
</del><ins>+        UString::Rep *key = m_singleEntryKey;
</ins><span class="cx">         if (key) {
</span><span class="cx">             UString k(key);
</span><span class="cx">             bool fitsInUInt32;
</span><span class="lines">@@ -632,8 +635,8 @@
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    int size = _table-&gt;size;
-    Entry *entries = _table-&gt;entries;
</del><ins>+    int size = m_u.table-&gt;size;
+    Entry *entries = m_u.table-&gt;entries;
</ins><span class="cx">     for (int i = 0; i != size; ++i) {
</span><span class="cx">         UString::Rep *key = entries[i].key;
</span><span class="cx">         if (isValid(key)) {
</span><span class="lines">@@ -650,14 +653,14 @@
</span><span class="cx"> {
</span><span class="cx">     int count = 0;
</span><span class="cx"> 
</span><del>-    if (!_table) {
</del><ins>+    if (!m_usingTable) {
</ins><span class="cx"> #if USE_SINGLE_ENTRY
</span><del>-        if (_singleEntry.key &amp;&amp; !(_singleEntry.attributes &amp; (ReadOnly | Function)))
</del><ins>+        if (m_singleEntryKey &amp;&amp; !(m_singleEntryAttributes &amp; (ReadOnly | Function)))
</ins><span class="cx">             ++count;
</span><span class="cx"> #endif
</span><span class="cx">     } else {
</span><del>-        int size = _table-&gt;size;
-        Entry *entries = _table-&gt;entries;
</del><ins>+        int size = m_u.table-&gt;size;
+        Entry *entries = m_u.table-&gt;entries;
</ins><span class="cx">         for (int i = 0; i != size; ++i)
</span><span class="cx">             if (isValid(entries[i].key) &amp;&amp; !(entries[i].attributes &amp; (ReadOnly | Function)))
</span><span class="cx">                 ++count;
</span><span class="lines">@@ -673,12 +676,12 @@
</span><span class="cx">     
</span><span class="cx">     SavedProperty *prop = p._properties.get();
</span><span class="cx">     
</span><del>-    if (!_table) {
</del><ins>+    if (!m_usingTable) {
</ins><span class="cx"> #if USE_SINGLE_ENTRY
</span><del>-        if (_singleEntry.key &amp;&amp; !(_singleEntry.attributes &amp; (ReadOnly | Function))) {
-            prop-&gt;key = Identifier(_singleEntry.key);
-            prop-&gt;value = _singleEntry.value;
-            prop-&gt;attributes = _singleEntry.attributes;
</del><ins>+        if (m_singleEntryKey &amp;&amp; !(m_singleEntryAttributes &amp; (ReadOnly | Function))) {
+            prop-&gt;key = Identifier(m_singleEntryKey);
+            prop-&gt;value = m_u.singleEntryValue;
+            prop-&gt;attributes = m_singleEntryAttributes;
</ins><span class="cx">             ++prop;
</span><span class="cx">         }
</span><span class="cx"> #endif
</span><span class="lines">@@ -691,8 +694,8 @@
</span><span class="cx"> 
</span><span class="cx">         // Get pointers to the entries in the buffer.
</span><span class="cx">         Entry** p = sortedEntries.data();
</span><del>-        int size = _table-&gt;size;
-        Entry* entries = _table-&gt;entries;
</del><ins>+        int size = m_u.table-&gt;size;
+        Entry* entries = m_u.table-&gt;entries;
</ins><span class="cx">         for (int i = 0; i != size; ++i) {
</span><span class="cx">             Entry *e = &amp;entries[i];
</span><span class="cx">             if (isValid(e-&gt;key) &amp;&amp; !(e-&gt;attributes &amp; (ReadOnly | Function)))
</span><span class="lines">@@ -723,13 +726,13 @@
</span><span class="cx"> 
</span><span class="cx"> void PropertyMap::checkConsistency()
</span><span class="cx"> {
</span><del>-    if (!_table)
</del><ins>+    if (!m_usingTable)
</ins><span class="cx">         return;
</span><span class="cx"> 
</span><span class="cx">     int count = 0;
</span><span class="cx">     int sentinelCount = 0;
</span><del>-    for (int j = 0; j != _table-&gt;size; ++j) {
-        UString::Rep *rep = _table-&gt;entries[j].key;
</del><ins>+    for (int j = 0; j != m_u.table-&gt;size; ++j) {
+        UString::Rep *rep = m_u.table-&gt;entries[j].key;
</ins><span class="cx">         if (!rep)
</span><span class="cx">             continue;
</span><span class="cx">         if (rep == deletedSentinel()) {
</span><span class="lines">@@ -737,23 +740,23 @@
</span><span class="cx">             continue;
</span><span class="cx">         }
</span><span class="cx">         unsigned h = rep-&gt;hash();
</span><del>-        int i = h &amp; _table-&gt;sizeMask;
</del><ins>+        int i = h &amp; m_u.table-&gt;sizeMask;
</ins><span class="cx">         int k = 0;
</span><del>-        while (UString::Rep *key = _table-&gt;entries[i].key) {
</del><ins>+        while (UString::Rep *key = m_u.table-&gt;entries[i].key) {
</ins><span class="cx">             if (rep == key)
</span><span class="cx">                 break;
</span><span class="cx">             if (k == 0)
</span><del>-                k = 1 | (h % _table-&gt;sizeMask);
-            i = (i + k) &amp; _table-&gt;sizeMask;
</del><ins>+                k = 1 | (h % m_u.table-&gt;sizeMask);
+            i = (i + k) &amp; m_u.table-&gt;sizeMask;
</ins><span class="cx">         }
</span><span class="cx">         assert(i == j);
</span><span class="cx">         ++count;
</span><span class="cx">     }
</span><del>-    assert(count == _table-&gt;keyCount);
-    assert(sentinelCount == _table-&gt;sentinelCount);
-    assert(_table-&gt;size &gt;= 16);
-    assert(_table-&gt;sizeMask);
-    assert(_table-&gt;size == _table-&gt;sizeMask + 1);
</del><ins>+    assert(count == m_u.table-&gt;keyCount);
+    assert(sentinelCount == m_u.table-&gt;sentinelCount);
+    assert(m_u.table-&gt;size &gt;= 16);
+    assert(m_u.table-&gt;sizeMask);
+    assert(m_u.table-&gt;size == m_u.table-&gt;sizeMask + 1);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> #endif // DO_CONSISTENCY_CHECK
</span></span></pre></div>
<a id="branchesjscollectortweaksJavaScriptCorekjsproperty_maph"></a>
<div class="modfile"><h4>Modified: branches/js-collector-tweaks/JavaScriptCore/kjs/property_map.h (20747 => 20748)</h4>
<pre class="diff"><span>
<span class="info">--- branches/js-collector-tweaks/JavaScriptCore/kjs/property_map.h        2007-04-06 08:26:13 UTC (rev 20747)
+++ branches/js-collector-tweaks/JavaScriptCore/kjs/property_map.h        2007-04-06 10:26:27 UTC (rev 20748)
</span><span class="lines">@@ -58,8 +58,7 @@
</span><span class="cx">         PropertyMapHashTableEntry() : key(0) { }
</span><span class="cx">         UString::Rep *key;
</span><span class="cx">         JSValue *value;
</span><del>-        short attributes;
-        short globalGetterSetterFlag;
</del><ins>+        int attributes;
</ins><span class="cx">         int index;
</span><span class="cx">     };
</span><span class="cx"> 
</span><span class="lines">@@ -86,8 +85,8 @@
</span><span class="cx">         void save(SavedProperties &amp;) const;
</span><span class="cx">         void restore(const SavedProperties &amp;p);
</span><span class="cx"> 
</span><del>-        bool hasGetterSetterProperties() const { return !!_singleEntry.globalGetterSetterFlag; }
-        void setHasGetterSetterProperties(bool f) { _singleEntry.globalGetterSetterFlag = f; }
</del><ins>+        bool hasGetterSetterProperties() const { return m_getterSetterFlag; }
+        void setHasGetterSetterProperties(bool f) { m_getterSetterFlag = f; }
</ins><span class="cx"> 
</span><span class="cx">         bool containsGettersOrSetters() const;
</span><span class="cx">     private:
</span><span class="lines">@@ -103,14 +102,24 @@
</span><span class="cx">         typedef PropertyMapHashTableEntry Entry;
</span><span class="cx">         typedef PropertyMapHashTable Table;
</span><span class="cx"> 
</span><del>-        Table *_table;
-        
-        Entry _singleEntry;
</del><ins>+        UString::Rep* m_singleEntryKey;
+        union {
+          JSValue* singleEntryValue;
+          Table* table;
+        } m_u;
+
+        short m_singleEntryAttributes;
+        bool m_getterSetterFlag;
+        bool m_usingTable;
</ins><span class="cx">     };
</span><span class="cx"> 
</span><del>-inline PropertyMap::PropertyMap() : _table(0)
</del><ins>+inline PropertyMap::PropertyMap() 
+  : m_singleEntryKey(0)
+  , m_getterSetterFlag(false)
+  , m_usingTable(false)
+
</ins><span class="cx"> {
</span><del>-    _singleEntry.globalGetterSetterFlag = 0;
</del><ins>+  m_u.table = 0;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> } // namespace
</span></span></pre>
</div>
</div>

</body>
</html>