Changeset 49331 in webkit for trunk/JavaScriptCore


Ignore:
Timestamp:
Oct 8, 2009, 4:24:55 PM (16 years ago)
Author:
[email protected]
Message:

Migrated some code that didn't belong out of Structure.

Patch by Geoffrey Garen <[email protected]> on 2009-10-08
Reviewed by Sam Weinig.

SunSpider says maybe 1.03x faster.

  • runtime/JSCell.h: Nixed Structure::markAggregate, and made marking of

a Structure's prototype the direct responsility of the object using it.
(Giving Structure a mark function was misleading because it implied that
all live structures get marked during GC, when they don't.)

  • runtime/JSGlobalObject.cpp:

(JSC::markIfNeeded):
(JSC::JSGlobalObject::markChildren): Added code to mark prototypes stored
on the global object. Maybe this wasn't necessary, but now we don't have
to wonder.

  • runtime/JSObject.cpp:

(JSC::JSObject::getPropertyNames):
(JSC::JSObject::getOwnPropertyNames):
(JSC::JSObject::getEnumerableNamesFromClassInfoTable):

  • runtime/JSObject.h:

(JSC::JSObject::markChildrenDirect):

  • runtime/PropertyNameArray.h:
  • runtime/Structure.cpp:
  • runtime/Structure.h:

(JSC::Structure::setEnumerationCache):
(JSC::Structure::enumerationCache): Moved property name gathering code
from Structure to JSObject because having a Structure iterate its JSObject
was a layering violation. A JSObject is implemented using a Structure; not
the other way around.

Location:
trunk/JavaScriptCore
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/ChangeLog

    r49328 r49331  
     12009-10-08  Geoffrey Garen  <[email protected]>
     2
     3        Reviewed by Sam Weinig.
     4
     5        Migrated some code that didn't belong out of Structure.
     6       
     7        SunSpider says maybe 1.03x faster.
     8
     9        * runtime/JSCell.h: Nixed Structure::markAggregate, and made marking of
     10        a Structure's prototype the direct responsility of the object using it.
     11        (Giving Structure a mark function was misleading because it implied that
     12        all live structures get marked during GC, when they don't.)
     13       
     14        * runtime/JSGlobalObject.cpp:
     15        (JSC::markIfNeeded):
     16        (JSC::JSGlobalObject::markChildren): Added code to mark prototypes stored
     17        on the global object. Maybe this wasn't necessary, but now we don't have
     18        to wonder.
     19
     20        * runtime/JSObject.cpp:
     21        (JSC::JSObject::getPropertyNames):
     22        (JSC::JSObject::getOwnPropertyNames):
     23        (JSC::JSObject::getEnumerableNamesFromClassInfoTable):
     24        * runtime/JSObject.h:
     25        (JSC::JSObject::markChildrenDirect):
     26        * runtime/PropertyNameArray.h:
     27        * runtime/Structure.cpp:
     28        * runtime/Structure.h:
     29        (JSC::Structure::setEnumerationCache):
     30        (JSC::Structure::enumerationCache): Moved property name gathering code
     31        from Structure to JSObject because having a Structure iterate its JSObject
     32        was a layering violation. A JSObject is implemented using a Structure; not
     33        the other way around.
     34
    1352009-10-08  Zoltan Herczeg  <[email protected]>
    236
  • trunk/JavaScriptCore/runtime/JSCell.h

    r49328 r49331  
    343343    }
    344344
    345     inline void Structure::markAggregate(MarkStack& markStack)
    346     {
    347         markStack.append(m_prototype);
    348     }
    349 
    350345    inline Heap* Heap::heap(JSValue v)
    351346    {
  • trunk/JavaScriptCore/runtime/JSGlobalObject.cpp

    r49328 r49331  
    9090{
    9191    if (s)
    92         s->markAggregate(markStack);
     92        markIfNeeded(markStack, s->storedPrototype());
    9393}
    9494
     
    395395
    396396    markIfNeeded(markStack, d()->errorStructure);
     397    markIfNeeded(markStack, d()->argumentsStructure);
     398    markIfNeeded(markStack, d()->arrayStructure);
     399    markIfNeeded(markStack, d()->booleanObjectStructure);
     400    markIfNeeded(markStack, d()->callbackConstructorStructure);
     401    markIfNeeded(markStack, d()->callbackFunctionStructure);
     402    markIfNeeded(markStack, d()->callbackObjectStructure);
     403    markIfNeeded(markStack, d()->dateStructure);
     404    markIfNeeded(markStack, d()->emptyObjectStructure);
     405    markIfNeeded(markStack, d()->errorStructure);
     406    markIfNeeded(markStack, d()->functionStructure);
     407    markIfNeeded(markStack, d()->numberObjectStructure);
     408    markIfNeeded(markStack, d()->prototypeFunctionStructure);
     409    markIfNeeded(markStack, d()->regExpMatchesArrayStructure);
     410    markIfNeeded(markStack, d()->regExpStructure);
     411    markIfNeeded(markStack, d()->stringObjectStructure);
    397412
    398413    // No need to mark the other structures, because their prototypes are all
  • trunk/JavaScriptCore/runtime/JSObject.cpp

    r49328 r49331  
    4343ASSERT_CLASS_FITS_IN_CELL(JSObject);
    4444
     45static inline void getEnumerablePropertyNames(ExecState* exec, const ClassInfo* classInfo, PropertyNameArray& propertyNames)
     46{
     47    // Add properties from the static hashtables of properties
     48    for (; classInfo; classInfo = classInfo->parentClass) {
     49        const HashTable* table = classInfo->propHashTable(exec);
     50        if (!table)
     51            continue;
     52        table->initializeIfNeeded(exec);
     53        ASSERT(table->table);
     54
     55        int hashSizeMask = table->compactSize - 1;
     56        const HashEntry* entry = table->table;
     57        for (int i = 0; i <= hashSizeMask; ++i, ++entry) {
     58            if (entry->key() && !(entry->attributes() & DontEnum))
     59                propertyNames.add(entry->key());
     60        }
     61    }
     62}
     63
    4564void JSObject::markChildren(MarkStack& markStack)
    4665{
     
    425444void JSObject::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
    426445{
    427     m_structure->getEnumerablePropertyNames(exec, propertyNames, this);
     446    bool shouldCache = propertyNames.shouldCache() && !(propertyNames.size() || m_structure->isDictionary());
     447
     448    if (shouldCache) {
     449        if (PropertyNameArrayData* data = m_structure->enumerationCache()) {
     450            if (data->cachedPrototypeChain() == m_structure->prototypeChain(exec)) {
     451                propertyNames.setData(data);
     452                return;
     453            }
     454
     455            m_structure->clearEnumerationCache();
     456        }
     457    }
     458
     459    getOwnPropertyNames(exec, propertyNames);
     460
     461    if (prototype().isObject()) {
     462        propertyNames.setShouldCache(false); // No need for our prototypes to waste memory on caching, since they're not being enumerated directly.
     463        JSObject* prototype = asObject(this->prototype());
     464        while(1) {
     465            if (!prototype->structure()->typeInfo().hasDefaultGetPropertyNames()) {
     466                prototype->getPropertyNames(exec, propertyNames);
     467                break;
     468            }
     469            prototype->getOwnPropertyNames(exec, propertyNames);
     470            JSValue nextProto = prototype->prototype();
     471            if (!nextProto.isObject())
     472                break;
     473            prototype = asObject(nextProto);
     474        }
     475    }
     476
     477    if (shouldCache) {
     478        StructureChain* protoChain = m_structure->prototypeChain(exec);
     479        if (!protoChain->isCacheable())
     480            return;
     481        RefPtr<PropertyNameArrayData> data = propertyNames.data();
     482        data->setCachedPrototypeChain(protoChain);
     483        data->setCachedStructure(m_structure);
     484        m_structure->setEnumerationCache(data.release());
     485    }
    428486}
    429487
    430488void JSObject::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
    431489{
    432     m_structure->getOwnEnumerablePropertyNames(exec, propertyNames, this);
     490    m_structure->getEnumerablePropertyNames(propertyNames);
     491    getEnumerablePropertyNames(exec, classInfo(), propertyNames);
    433492}
    434493
  • trunk/JavaScriptCore/runtime/JSObject.h

    r49328 r49331  
    683683    JSCell::markChildren(markStack);
    684684
    685     m_structure->markAggregate(markStack);
     685    markStack.append(prototype());
    686686   
    687687    PropertyStorage storage = propertyStorage();
  • trunk/JavaScriptCore/runtime/PropertyNameArray.h

    r49328 r49331  
    2424#include "CallFrame.h"
    2525#include "Identifier.h"
    26 #include "Structure.h"
    2726#include <wtf/HashSet.h>
    2827#include <wtf/Vector.h>
    2928
    3029namespace JSC {
     30   
     31    class Structure;
     32    class StructureChain;
    3133
    3234    class PropertyNameArrayData : public RefCounted<PropertyNameArrayData> {
  • trunk/JavaScriptCore/runtime/Structure.cpp

    r49328 r49331  
    283283}
    284284
    285 void Structure::getOwnEnumerablePropertyNames(ExecState* exec, PropertyNameArray& propertyNames, JSObject* baseObject)
    286 {
    287     getEnumerableNamesFromPropertyTable(propertyNames);
    288     getEnumerableNamesFromClassInfoTable(exec, baseObject->classInfo(), propertyNames);
    289 }
    290 
    291 void Structure::getEnumerablePropertyNames(ExecState* exec, PropertyNameArray& propertyNames, JSObject* baseObject)
    292 {
    293     bool shouldCache = propertyNames.shouldCache() && !(propertyNames.size() || isDictionary());
    294 
    295     if (shouldCache && m_cachedPropertyNameArrayData) {
    296         if (m_cachedPropertyNameArrayData->cachedPrototypeChain() == prototypeChain(exec)) {
    297             propertyNames.setData(m_cachedPropertyNameArrayData);
    298             return;
    299         }
    300         clearEnumerationCache();
    301     }
    302 
    303     baseObject->getOwnPropertyNames(exec, propertyNames);
    304 
    305     if (m_prototype.isObject()) {
    306         propertyNames.setShouldCache(false); // No need for our prototypes to waste memory on caching, since they're not being enumerated directly.
    307         JSObject* prototype = asObject(m_prototype);
    308         while(1) {
    309             if (!prototype->structure()->typeInfo().hasDefaultGetPropertyNames()) {
    310                 prototype->getPropertyNames(exec, propertyNames);
    311                 break;
    312             }
    313             prototype->getOwnPropertyNames(exec, propertyNames);
    314             JSValue nextProto = prototype->prototype();
    315             if (!nextProto.isObject())
    316                 break;
    317             prototype = asObject(nextProto);
    318         }
    319     }
    320 
    321     if (shouldCache) {
    322         StructureChain* protoChain = prototypeChain(exec);
    323         m_cachedPropertyNameArrayData = propertyNames.data();
    324         if (!protoChain->isCacheable())
    325             return;
    326         m_cachedPropertyNameArrayData->setCachedPrototypeChain(protoChain);
    327         m_cachedPropertyNameArrayData->setCachedStructure(this);
    328     }
    329 }
    330 
    331285void Structure::clearEnumerationCache()
    332286{
     
    10581012}
    10591013
    1060 void Structure::getEnumerableNamesFromPropertyTable(PropertyNameArray& propertyNames)
     1014void Structure::getEnumerablePropertyNames(PropertyNameArray& propertyNames)
    10611015{
    10621016    materializePropertyMapIfNecessary();
     
    11121066        for (size_t i = 0; i < sortedEnumerables.size(); ++i)
    11131067            propertyNames.add(sortedEnumerables[i]->key);
    1114     }
    1115 }
    1116 
    1117 void Structure::getEnumerableNamesFromClassInfoTable(ExecState* exec, const ClassInfo* classInfo, PropertyNameArray& propertyNames)
    1118 {
    1119     // Add properties from the static hashtables of properties
    1120     for (; classInfo; classInfo = classInfo->parentClass) {
    1121         const HashTable* table = classInfo->propHashTable(exec);
    1122         if (!table)
    1123             continue;
    1124         table->initializeIfNeeded(exec);
    1125         ASSERT(table->table);
    1126 
    1127         int hashSizeMask = table->compactSize - 1;
    1128         const HashEntry* entry = table->table;
    1129         for (int i = 0; i <= hashSizeMask; ++i, ++entry) {
    1130             if (entry->key() && !(entry->attributes() & DontEnum))
    1131                 propertyNames.add(entry->key());
    1132         }
    11331068    }
    11341069}
  • trunk/JavaScriptCore/runtime/Structure.h

    r49328 r49331  
    3131#include "JSValue.h"
    3232#include "PropertyMapHashTable.h"
     33#include "PropertyNameArray.h"
    3334#include "StructureChain.h"
    3435#include "StructureTransitionTable.h"
     
    7778        ~Structure();
    7879
    79         void markAggregate(MarkStack&);
    80 
    8180        // These should be used with caution. 
    8281        size_t addPropertyWithoutTransition(const Identifier& propertyName, unsigned attributes, JSCell* specificValue);
     
    117116        }
    118117
    119         void getEnumerablePropertyNames(ExecState*, PropertyNameArray&, JSObject*);
    120         void getOwnEnumerablePropertyNames(ExecState*, PropertyNameArray&, JSObject*);
    121 
    122118        bool hasGetterSetterProperties() const { return m_hasGetterSetterProperties; }
    123119        void setHasGetterSetterProperties(bool hasGetterSetterProperties) { m_hasGetterSetterProperties = hasGetterSetterProperties; }
     
    127123        JSCell* specificValue() { return m_specificValueInPrevious; }
    128124        void despecifyDictionaryFunction(const Identifier& propertyName);
     125
     126        void setEnumerationCache(PassRefPtr<PropertyNameArrayData> data) { m_cachedPropertyNameArrayData = data; }
     127        PropertyNameArrayData* enumerationCache() { return m_cachedPropertyNameArrayData.get(); }
     128        void clearEnumerationCache();
     129        void getEnumerablePropertyNames(PropertyNameArray&);
    129130
    130131    private:
     
    141142        size_t remove(const Identifier& propertyName);
    142143        void addAnonymousSlots(unsigned slotCount);
    143         void getEnumerableNamesFromPropertyTable(PropertyNameArray&);
    144         void getEnumerableNamesFromClassInfoTable(ExecState*, const ClassInfo*, PropertyNameArray&);
    145144
    146145        void expandPropertyMapHashTable();
     
    162161            materializePropertyMap();
    163162        }
    164 
    165         void clearEnumerationCache();
    166163
    167164        signed char transitionCount() const
Note: See TracChangeset for help on using the changeset viewer.