<!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 <C.Hyde@parableuk.force9.co.uk>
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 <C.Hyde@parableuk.force9.co.uk>
+ 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 <mjs@apple.com>
+
+ 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<bool is32Bit, bool is64Bit> struct CellSize;
</span><del>-template<> struct CellSize<true, false> { static const size_t m_value = 48; }; // 32-bit
-template<> struct CellSize<false, true> { static const size_t m_value = 80; }; // 64-bit
</del><ins>+template<> struct CellSize<true, false> { static const size_t m_value = 40; }; // 32-bit
+template<> struct CellSize<false, true> { 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->deref();
</span><span class="cx"> #endif
</span><span class="cx"> return;
</span><span class="cx"> }
</span><span class="cx">
</span><del>- int minimumKeysToProcess = _table->keyCount + _table->sentinelCount;
- Entry *entries = _table->entries;
</del><ins>+ int minimumKeysToProcess = m_u.table->keyCount + m_u.table->sentinelCount;
+ Entry *entries = m_u.table->entries;
</ins><span class="cx"> for (int i = 0; i < 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->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->size;
- Entry *entries = _table->entries;
</del><ins>+ int size = m_u.table->size;
+ Entry *entries = m_u.table->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">@@ -155,8 +153,8 @@
</span><span class="cx"> entries[i].value = 0;
</span><span class="cx"> }
</span><span class="cx"> }
</span><del>- _table->keyCount = 0;
- _table->sentinelCount = 0;
</del><ins>+ m_u.table->keyCount = 0;
+ m_u.table->sentinelCount = 0;
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> JSValue *PropertyMap::get(const Identifier &name, unsigned &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->hash();
</span><del>- int sizeMask = _table->sizeMask;
- Entry *entries = _table->entries;
</del><ins>+ int sizeMask = m_u.table->sizeMask;
+ Entry *entries = m_u.table->entries;
</ins><span class="cx"> int i = h & 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->hash();
</span><del>- int sizeMask = _table->sizeMask;
- Entry *entries = _table->entries;
</del><ins>+ int sizeMask = m_u.table->sizeMask;
+ Entry *entries = m_u.table->entries;
</ins><span class="cx"> int i = h & 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 &_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->hash();
</span><del>- int sizeMask = _table->sizeMask;
- Entry *entries = _table->entries;
</del><ins>+ int sizeMask = m_u.table->sizeMask;
+ Entry *entries = m_u.table->entries;
</ins><span class="cx"> int i = h & 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 && !(roCheck && (_singleEntry.attributes & ReadOnly))) {
- _singleEntry.value = value;
</del><ins>+ if (rep == key && !(roCheck && (m_singleEntryAttributes & ReadOnly))) {
+ m_u.singleEntryValue = value;
</ins><span class="cx"> return;
</span><span class="cx"> }
</span><span class="cx"> } else {
</span><span class="cx"> rep->ref();
</span><del>- _singleEntry.key = rep;
- _singleEntry.value = value;
- _singleEntry.attributes = static_cast<short>(attributes);
</del><ins>+ m_singleEntryKey = rep;
+ m_u.singleEntryValue = value;
+ m_singleEntryAttributes = static_cast<short>(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->keyCount * 2 >= _table->size)
</del><ins>+ if (!m_usingTable || m_u.table->keyCount * 2 >= m_u.table->size)
</ins><span class="cx"> expand();
</span><span class="cx">
</span><span class="cx"> unsigned h = rep->hash();
</span><del>- int sizeMask = _table->sizeMask;
- Entry *entries = _table->entries;
</del><ins>+ int sizeMask = m_u.table->sizeMask;
+ Entry *entries = m_u.table->entries;
</ins><span class="cx"> int i = h & 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 && (_table->entries[i].attributes & ReadOnly))
</del><ins>+ if (roCheck && (m_u.table->entries[i].attributes & 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->sentinelCount;
</del><ins>+ --m_u.table->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<short>(attributes);
</span><del>- entries[i].index = ++_table->lastIndexUsed;
- ++_table->keyCount;
</del><ins>+ entries[i].index = ++m_u.table->lastIndexUsed;
+ ++m_u.table->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->hash();
</span><del>- int sizeMask = _table->sizeMask;
- Entry *entries = _table->entries;
</del><ins>+ int sizeMask = m_u.table->sizeMask;
+ Entry *entries = m_u.table->entries;
</ins><span class="cx"> int i = h & 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->size : 0;
</del><ins>+ Table *oldTable = m_u.table;
+ int oldTableSize = m_usingTable ? oldTable->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->size);
- rehash(_table->size);
</del><ins>+ assert(m_u.table);
+ assert(m_u.table->size);
+ rehash(m_u.table->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->size : 0;
+ int oldTableKeyCount = m_usingTable ? oldTable->keyCount : 0;
</ins><span class="cx">
</span><del>- Table *oldTable = _table;
- int oldTableSize = oldTable ? oldTable->size : 0;
- int oldTableKeyCount = oldTable ? oldTable->keyCount : 0;
-
- _table = (Table *)fastCalloc(1, sizeof(Table) + (newTableSize - 1) * sizeof(Entry) );
- _table->size = newTableSize;
- _table->sizeMask = newTableSize - 1;
- _table->keyCount = oldTableKeyCount;
</del><ins>+ m_u.table = (Table *)fastCalloc(1, sizeof(Table) + (newTableSize - 1) * sizeof(Entry) );
+ m_u.table->size = newTableSize;
+ m_u.table->sizeMask = newTableSize - 1;
+ m_u.table->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->keyCount;
- assert(_table->keyCount == 1);
</del><ins>+ ++m_u.table->keyCount;
+ assert(m_u.table->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->lastIndexUsed = lastIndexUsed;
</del><ins>+ m_u.table->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->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->hash();
</span><del>- int sizeMask = _table->sizeMask;
- Entry *entries = _table->entries;
</del><ins>+ int sizeMask = m_u.table->sizeMask;
+ Entry *entries = m_u.table->entries;
</ins><span class="cx"> int i = h & 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->keyCount >= 1);
- --_table->keyCount;
- ++_table->sentinelCount;
</del><ins>+ assert(m_u.table->keyCount >= 1);
+ --m_u.table->keyCount;
+ ++m_u.table->sentinelCount;
</ins><span class="cx">
</span><del>- if (_table->sentinelCount * 4 >= _table->size)
</del><ins>+ if (m_u.table->sentinelCount * 4 >= m_u.table->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->marked())
</span><span class="cx"> v->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->keyCount;
- Entry *entries = _table->entries;
</del><ins>+ int minimumKeysToProcess = m_u.table->keyCount;
+ Entry *entries = m_u.table->entries;
</ins><span class="cx"> for (int i = 0; i < 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 & GetterSetter);
</del><ins>+ return !!(m_singleEntryAttributes & 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->size; ++i) {
- if (_table->entries[i].attributes & GetterSetter)
</del><ins>+ for (int i = 0; i != m_u.table->size; ++i) {
+ if (m_u.table->entries[i].attributes & 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& 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 && !(_singleEntry.attributes & DontEnum))
</del><ins>+ UString::Rep* key = m_singleEntryKey;
+ if (key && !(m_singleEntryAttributes & 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<Entry*, smallMapThreshold> sortedEnumerables(_table->keyCount);
</del><ins>+ Vector<Entry*, smallMapThreshold> sortedEnumerables(m_u.table->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->size;
- Entry* entries = _table->entries;
</del><ins>+ int size = m_u.table->size;
+ Entry* entries = m_u.table->entries;
</ins><span class="cx"> for (int i = 0; i != size; ++i) {
</span><span class="cx"> Entry* e = &entries[i];
</span><span class="cx"> if (e->key && !(e->attributes & DontEnum))
</span><span class="lines">@@ -618,9 +621,9 @@
</span><span class="cx">
</span><span class="cx"> void PropertyMap::getSparseArrayPropertyNames(PropertyNameArray& 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->size;
- Entry *entries = _table->entries;
</del><ins>+ int size = m_u.table->size;
+ Entry *entries = m_u.table->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 && !(_singleEntry.attributes & (ReadOnly | Function)))
</del><ins>+ if (m_singleEntryKey && !(m_singleEntryAttributes & (ReadOnly | Function)))
</ins><span class="cx"> ++count;
</span><span class="cx"> #endif
</span><span class="cx"> } else {
</span><del>- int size = _table->size;
- Entry *entries = _table->entries;
</del><ins>+ int size = m_u.table->size;
+ Entry *entries = m_u.table->entries;
</ins><span class="cx"> for (int i = 0; i != size; ++i)
</span><span class="cx"> if (isValid(entries[i].key) && !(entries[i].attributes & (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 && !(_singleEntry.attributes & (ReadOnly | Function))) {
- prop->key = Identifier(_singleEntry.key);
- prop->value = _singleEntry.value;
- prop->attributes = _singleEntry.attributes;
</del><ins>+ if (m_singleEntryKey && !(m_singleEntryAttributes & (ReadOnly | Function))) {
+ prop->key = Identifier(m_singleEntryKey);
+ prop->value = m_u.singleEntryValue;
+ prop->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->size;
- Entry* entries = _table->entries;
</del><ins>+ int size = m_u.table->size;
+ Entry* entries = m_u.table->entries;
</ins><span class="cx"> for (int i = 0; i != size; ++i) {
</span><span class="cx"> Entry *e = &entries[i];
</span><span class="cx"> if (isValid(e->key) && !(e->attributes & (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->size; ++j) {
- UString::Rep *rep = _table->entries[j].key;
</del><ins>+ for (int j = 0; j != m_u.table->size; ++j) {
+ UString::Rep *rep = m_u.table->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->hash();
</span><del>- int i = h & _table->sizeMask;
</del><ins>+ int i = h & m_u.table->sizeMask;
</ins><span class="cx"> int k = 0;
</span><del>- while (UString::Rep *key = _table->entries[i].key) {
</del><ins>+ while (UString::Rep *key = m_u.table->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->sizeMask);
- i = (i + k) & _table->sizeMask;
</del><ins>+ k = 1 | (h % m_u.table->sizeMask);
+ i = (i + k) & m_u.table->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->keyCount);
- assert(sentinelCount == _table->sentinelCount);
- assert(_table->size >= 16);
- assert(_table->sizeMask);
- assert(_table->size == _table->sizeMask + 1);
</del><ins>+ assert(count == m_u.table->keyCount);
+ assert(sentinelCount == m_u.table->sentinelCount);
+ assert(m_u.table->size >= 16);
+ assert(m_u.table->sizeMask);
+ assert(m_u.table->size == m_u.table->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 &) const;
</span><span class="cx"> void restore(const SavedProperties &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>