Changeset 36032 in webkit for trunk/JavaScriptCore/kjs


Ignore:
Timestamp:
Sep 2, 2008, 7:31:45 PM (17 years ago)
Author:
[email protected]
Message:

JavaScriptCore:

2008-09-02 Geoffrey Garen <[email protected]>

Reviewed by Sam Weinig.


Implemented the rest of Darin's review comments for the 09-01 inline
caching patch.


SunSpider says 0.5% faster, but that seems like noise.

  • JavaScriptCore.xcodeproj/project.pbxproj: Put PutPropertySlot into its own file, and added BatchedTransitionOptimizer.
  • VM/CodeBlock.cpp: (KJS::CodeBlock::~CodeBlock): Use array indexing instead of a pointer iterator.
  • VM/CodeGenerator.cpp: (KJS::CodeGenerator::CodeGenerator): Used BatchedTransitionOptimizer to make batched put and remove for declared variables fast, without forever pessimizing the global object. Removed the old getDirect/removeDirect hack that tried to do the same in a more limited way.
  • VM/CodeGenerator.h: Moved IdentifierRepHash to the KJS namespace since it doesn't specialize anything in WTF.
  • VM/Machine.cpp: (KJS::Machine::Machine): Nixed the DummyConstruct tag because it was confusingly named.

(KJS::Machine::execute): Used BatchedTransitionOptimizer, as above. Fixed
up some comments.

(KJS::cachePrototypeChain): Cast to JSObject*, since it's more specific.

(KJS::Machine::tryCachePutByID): Use isNull() instead of comparing to
jsNull(), since isNull() leaves more options open for the future.
(KJS::Machine::tryCacheGetByID): ditto
(KJS::Machine::privateExecute): ditto

  • VM/SamplingTool.cpp: (KJS::SamplingTool::dump): Use C++-style cast, to match our style guidelines.
  • kjs/BatchedTransitionOptimizer.h: Added. New class that allows host code to add a batch of properties to an object in an efficient way.
  • kjs/JSActivation.cpp: Use isNull(), as above.
  • kjs/JSArray.cpp: Get rid of DummyConstruct tag, as above.
  • kjs/JSArray.h:
  • kjs/JSGlobalData.cpp: Nixed two unused StructureIDs.
  • kjs/JSGlobalData.h:
  • kjs/JSImmediate.cpp: Use isNull(), as above.
  • kjs/JSObject.cpp: (KJS::JSObject::mark): Moved mark tracing code elsewhere, to make this function more readable.

(KJS::JSObject::put): Use isNull(), as above.

(KJS::JSObject::createInheritorID): Return a raw pointer, since the
object is owned by a data member, not necessarily the caller.

  • kjs/JSObject.h:
  • kjs/JSString.cpp: Use isNull(), as above.
  • kjs/PropertyMap.h: Updated to use PropertySlot::invalidOffset.
  • kjs/PropertySlot.h: Changed KJS_INVALID_OFFSET to WTF::notFound because C macros are so 80's.
  • kjs/PutPropertySlot.h: Added. Split out of PropertySlot.h. Also renamed PutPropertySlot::SlotType to PutPropertySlot::Type, and slotBase to base, since "slot" was redundant.
  • kjs/StructureID.cpp: Added a new transition *away* from dictionary status, to support BatchedTransitionOptimizer.

(KJS::StructureIDChain::StructureIDChain): No need to store m_size as
a data member, so keep it in a local, which might be faster.

  • kjs/StructureID.h:
  • kjs/SymbolTable.h: Moved IdentifierRepHash to KJS namespace, as above.
  • kjs/ustring.h:

JavaScriptGlue:

2008-09-02 Geoffrey Garen <[email protected]>

Reviewed by Sam Weinig.


Implemented the rest of Darin's review comments for the 09-01 inline
caching patch.


  • ForwardingHeaders/kjs/PutPropertySlot.h: Added.
Location:
trunk/JavaScriptCore/kjs
Files:
2 added
16 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/kjs/JSActivation.cpp

    r36016 r36032  
    8080    // activation object getter properties or a prototype.
    8181    ASSERT(!hasGetterSetterProperties());
    82     ASSERT(prototype() == jsNull());
     82    ASSERT(prototype()->isNull());
    8383    return false;
    8484}
  • trunk/JavaScriptCore/kjs/JSArray.cpp

    r36016 r36032  
    126126#endif
    127127
    128 JSArray::JSArray(DummyConstructTag)
    129     : JSObject(StructureID::create(jsNull()))
     128JSArray::JSArray(PassRefPtr<StructureID> structureID)
     129    : JSObject(structureID)
    130130{
    131131    unsigned initialCapacity = 0;
  • trunk/JavaScriptCore/kjs/JSArray.h

    r36016 r36032  
    3939    class JSArray : public JSObject {
    4040    public:
    41         enum DummyConstructTag { DummyConstruct };
    42         JSArray(DummyConstructTag);
     41        JSArray(PassRefPtr<StructureID>);
    4342        JSArray(JSObject* prototype, unsigned initialLength);
    4443        JSArray(ExecState* exec, JSObject* prototype, const ArgList& initialValues);
  • trunk/JavaScriptCore/kjs/JSGlobalData.cpp

    r36016 r36032  
    7777    , stringTable(&KJS::stringTable)
    7878#endif
    79     , stringStructureID(StructureID::create(jsNull()))
    80     , numberStructureID(StructureID::create(jsNull()))
    8179    , nullProtoStructureID(StructureID::create(jsNull()))
    8280    , identifierTable(createIdentifierTable())
  • trunk/JavaScriptCore/kjs/JSGlobalData.h

    r36016 r36032  
    7474        const HashTable* stringTable;
    7575       
    76         RefPtr<StructureID> stringStructureID;
    77         RefPtr<StructureID> numberStructureID;
    7876        RefPtr<StructureID> nullProtoStructureID;
    7977
  • trunk/JavaScriptCore/kjs/JSImmediate.cpp

    r36016 r36032  
    4141        return constructBooleanFromImmediateBoolean(exec, const_cast<JSValue*>(v));
    4242   
    43     JSNotAnObjectErrorStub* exception = createNotAnObjectErrorStub(exec, v == jsNull());
     43    JSNotAnObjectErrorStub* exception = createNotAnObjectErrorStub(exec, v->isNull());
    4444    exec->setException(exception);
    4545    return new (exec) JSNotAnObject(exec, exception);
     
    5454        return exec->lexicalGlobalObject()->booleanPrototype();
    5555
    56     JSNotAnObjectErrorStub* exception = createNotAnObjectErrorStub(exec, v == jsNull());
     56    JSNotAnObjectErrorStub* exception = createNotAnObjectErrorStub(exec, v->isNull());
    5757    exec->setException(exception);
    5858    return new (exec) JSNotAnObject(exec, exception);
     
    6868    if (v == jsBoolean(true))
    6969        return "true";
    70     if (v == jsNull())
     70    if (v->isNull())
    7171        return "null";
    7272    ASSERT(v == jsUndefined());
  • trunk/JavaScriptCore/kjs/JSObject.cpp

    r36016 r36032  
    3939#include <wtf/Assertions.h>
    4040
    41 #define JAVASCRIPT_MARK_TRACING 0
     41#define JSOBJECT_MARK_TRACING 0
     42
     43#if JSOBJECT_MARK_TRACING
     44
     45#define JSOBJECT_MARK_BEGIN() \
     46    static int markStackDepth = 0; \
     47    for (int i = 0; i < markStackDepth; i++) \
     48        putchar('-'); \
     49    printf("%s (%p)\n", className().UTF8String().c_str(), this); \
     50    markStackDepth++; \
     51
     52#define JSOBJECT_MARK_END() \
     53    markStackDepth--;
     54
     55#else // JSOBJECT_MARK_TRACING
     56
     57#define JSOBJECT_MARK_BEGIN()
     58#define JSOBJECT_MARK_END()
     59
     60#endif // JSOBJECT_MARK_TRACING
    4261
    4362namespace KJS {
     
    4766void JSObject::mark()
    4867{
     68    JSOBJECT_MARK_BEGIN();
     69
    4970    JSCell::mark();
    50 
    51 #if JAVASCRIPT_MARK_TRACING
    52     static int markStackDepth = 0;
    53     markStackDepth++;
    54     for (int i = 0; i < markStackDepth; i++)
    55         putchar('-');
    56     printf("%s (%p)\n", className().UTF8String().c_str(), this);
    57 #endif
    58 
    5971    m_structureID->mark();
    6072    m_propertyMap.mark();
    6173
    62 #if JAVASCRIPT_MARK_TRACING
    63     markStackDepth--;
    64 #endif
     74    JSOBJECT_MARK_END();
    6575}
    6676
     
    93103
    94104        // Setting __proto__ to a non-object, non-null value is silently ignored to match Mozilla.
    95         if (!proto && value != jsNull())
     105        if (!proto && !value->isNull())
    96106            return;
    97107       
     
    112122    for (JSObject* obj = this; !obj->m_propertyMap.hasGetterSetterProperties(); obj = static_cast<JSObject*>(prototype)) {
    113123        prototype = obj->prototype();
    114         if (prototype == jsNull()) {
     124        if (prototype->isNull()) {
    115125            putDirect(propertyName, value, 0, true, slot);
    116126            return;
     
    145155
    146156        prototype = obj->prototype();
    147         if (prototype == jsNull())
     157        if (prototype->isNull())
    148158            break;
    149159    }
     
    478488    m_propertyMap.remove(propertyName);
    479489    if (!m_structureID->isDictionary()) {
    480         RefPtr<StructureID> structureID = StructureID::dictionaryTransition(m_structureID);
     490        RefPtr<StructureID> structureID = StructureID::toDictionaryTransition(m_structureID);
    481491        setStructureID(structureID.release());
    482492    }
     
    496506}
    497507
    498 PassRefPtr<StructureID> JSObject::createInheritorID()
     508StructureID* JSObject::createInheritorID()
    499509{
    500510    m_inheritorID = StructureID::create(this);
    501     return m_inheritorID;
     511    return m_inheritorID.get();
    502512}
    503513
  • trunk/JavaScriptCore/kjs/JSObject.h

    r36016 r36032  
    3131#include "PropertyMap.h"
    3232#include "PropertySlot.h"
     33#include "PutPropertySlot.h"
    3334#include "ScopeChain.h"
    3435#include "StructureID.h"
     
    5354
    5455    class JSObject : public JSCell {
     56        friend class BatchedTransitionOptimizer;
     57
    5558    public:
    5659        JSObject(PassRefPtr<StructureID>);
     
    6568        void setPrototype(JSValue* prototype);
    6669       
    67         PassRefPtr<StructureID> inheritorID();
     70        StructureID* inheritorID();
    6871
    6972        virtual UString className() const;
     
    153156        const HashEntry* findPropertyHashEntry(ExecState*, const Identifier& propertyName) const;
    154157        void setStructureID(PassRefPtr<StructureID>);
    155         PassRefPtr<StructureID> createInheritorID();
     158        StructureID* createInheritorID();
    156159
    157160        PropertyMap m_propertyMap;
     
    162165
    163166inline JSObject::JSObject(JSObject* prototype)
    164     : JSCell(prototype->inheritorID().releaseRef()) // ~JSObject balances this ref()
     167    : JSCell(prototype->inheritorID())
    165168{
    166169    ASSERT(m_structureID);
    167170    ASSERT(this->prototype());
    168     ASSERT(this->prototype() == jsNull() || Heap::heap(this) == Heap::heap(this->prototype()));
     171    ASSERT(this->prototype()->isNull() || Heap::heap(this) == Heap::heap(this->prototype()));
     172    m_structureID->ref(); // ~JSObject balances this ref()
    169173}
    170174
     
    199203}
    200204
    201 inline PassRefPtr<StructureID> JSObject::inheritorID()
     205inline StructureID* JSObject::inheritorID()
    202206{
    203207    if (m_inheritorID)
  • trunk/JavaScriptCore/kjs/JSString.cpp

    r36006 r36032  
    9191    slot.setBase(this);
    9292    JSObject* object;
    93     for (JSValue* prototype = exec->lexicalGlobalObject()->stringPrototype(); prototype != jsNull(); prototype = object->prototype()) {
     93    for (JSValue* prototype = exec->lexicalGlobalObject()->stringPrototype(); !prototype->isNull(); prototype = object->prototype()) {
    9494        ASSERT(prototype->isObject());
    9595        object = static_cast<JSObject*>(prototype);
  • trunk/JavaScriptCore/kjs/PropertyMap.cpp

    r36018 r36032  
    332332            m_singleEntryAttributes = static_cast<short>(attributes);
    333333            checkConsistency();
    334             slot.setNewProperty(slotBase, KJS_INVALID_OFFSET);
     334            slot.setNewProperty(slotBase, WTF::notFound);
    335335            return;
    336336        }
  • trunk/JavaScriptCore/kjs/PropertyMap.h

    r36016 r36032  
    2424#include "PropertySlot.h"
    2525#include "identifier.h"
     26#include <wtf/NotFound.h>
    2627
    2728namespace KJS {
     
    105106        }
    106107
    107         size_t offsetForLocation(JSValue** location) { return m_usingTable ? offsetForTableLocation(location) : KJS_INVALID_OFFSET; }
     108        size_t offsetForLocation(JSValue** location) { return m_usingTable ? offsetForTableLocation(location) : WTF::notFound; }
    108109
    109110        void mark() const;
  • trunk/JavaScriptCore/kjs/PropertySlot.h

    r36016 r36032  
    2626#include "identifier.h"
    2727#include <wtf/Assertions.h>
     28#include <wtf/NotFound.h>
    2829
    2930namespace KJS {
     
    3536#define KJS_VALUE_SLOT_MARKER 0
    3637#define KJS_REGISTER_SLOT_MARKER reinterpret_cast<GetValueFunc>(1)
    37 #define KJS_INVALID_OFFSET static_cast<size_t>(-1)
    3838
    3939    class PropertySlot {
    4040    public:
    4141        PropertySlot()
    42             : m_offset(KJS_INVALID_OFFSET)
     42            : m_offset(WTF::notFound)
    4343        {
    4444            clearBase();
     
    4848        explicit PropertySlot(JSValue* base)
    4949            : m_slotBase(base)
    50             , m_offset(KJS_INVALID_OFFSET)
     50            , m_offset(WTF::notFound)
    5151        {
    5252            clearValue();
     
    7373        }
    7474
    75         bool isCacheable() const { return m_offset != KJS_INVALID_OFFSET; }
     75        bool isCacheable() const { return m_offset != WTF::notFound; }
    7676        size_t cachedOffset() const
    7777        {
     
    220220        size_t m_offset;
    221221    };
    222    
    223     class PutPropertySlot {
    224     public:
    225         enum SlotType {
    226             Invalid,
    227             ExistingProperty,
    228             NewProperty,
    229         };
    230 
    231         PutPropertySlot()
    232             : m_type(Invalid)
    233             , m_base(0)
    234         {
    235         }
    236 
    237         void setExistingProperty(JSObject* base, size_t offset)
    238         {
    239             m_type = ExistingProperty;
    240             m_base = base;
    241             m_offset = offset;
    242         }
    243 
    244         void setNewProperty(JSObject* base, size_t offset)
    245         {
    246             m_type = NewProperty;
    247             m_base = base;
    248             m_offset = offset;
    249         }
    250 
    251         SlotType type() const { return m_type; }
    252         JSObject* slotBase() const { return m_base; }
    253 
    254         bool isCacheable() const { return m_type != Invalid; }
    255         size_t cachedOffset() const {
    256             ASSERT(isCacheable());
    257             return m_offset;
    258         }
    259 
    260     private:
    261         SlotType m_type;
    262         JSObject* m_base;
    263         size_t m_offset;
    264     };
    265222
    266223} // namespace KJS
  • trunk/JavaScriptCore/kjs/StructureID.cpp

    r36018 r36032  
    2929
    3030#include "identifier.h"
    31 #include "JSCell.h"
     31#include "JSObject.h"
    3232#include <wtf/RefPtr.h>
    3333
     
    5454
    5555    if (structureID->m_transitionCount > s_maxTransitionLength)
    56         return dictionaryTransition(structureID);
     56        return toDictionaryTransition(structureID);
    5757
    5858    RefPtr<StructureID> transition = create(structureID->m_prototype);
     
    6666}
    6767
    68 PassRefPtr<StructureID> StructureID::dictionaryTransition(StructureID* structureID)
     68PassRefPtr<StructureID> StructureID::toDictionaryTransition(StructureID* structureID)
    6969{
    7070    ASSERT(!structureID->m_isDictionary);
     
    7272    RefPtr<StructureID> transition = create(structureID->m_prototype);
    7373    transition->m_isDictionary = true;
    74     transition->m_transitionCount = structureID->m_transitionCount + 1;
    7574    return transition.release();
     75}
     76
     77PassRefPtr<StructureID> StructureID::fromDictionaryTransition(StructureID* structureID)
     78{
     79    ASSERT(structureID->m_isDictionary);
     80
     81    // Since dictionary StructureIDs are not shared, and no opcodes specialize
     82    // for them, we don't need to allocate a new StructureID when transitioning
     83    // to non-dictionary status.
     84    structureID->m_isDictionary = false;
     85    return structureID;
    7686}
    7787
     
    99109
    100110StructureIDChain::StructureIDChain(StructureID* structureID)
    101     : m_size(0)
    102111{
     112    size_t size = 0;
     113
    103114    StructureID* tmp = structureID;
    104     while (tmp->prototype() != jsNull()) {
    105         ++m_size;
     115    while (!tmp->prototype()->isNull()) {
     116        ++size;
    106117        tmp = static_cast<JSCell*>(tmp->prototype())->structureID();
    107118    }
    108119
    109     m_vector.set(new RefPtr<StructureID>[m_size]);
     120    m_vector.set(new RefPtr<StructureID>[size]);
    110121
    111     for (size_t i = 0; i < m_size; ++i) {
     122    for (size_t i = 0; i < size; ++i) {
    112123        m_vector[i] = structureID;
    113         structureID = static_cast<JSCell*>(structureID->prototype())->structureID();
     124        structureID = static_cast<JSObject*>(structureID->prototype())->structureID();
    114125    }
    115126}
  • trunk/JavaScriptCore/kjs/StructureID.h

    r36016 r36032  
    4949        static PassRefPtr<StructureID> addPropertyTransition(StructureID*, const Identifier& name);
    5050        static PassRefPtr<StructureID> getterSetterTransition(StructureID*);
    51         static PassRefPtr<StructureID> dictionaryTransition(StructureID*);
     51        static PassRefPtr<StructureID> toDictionaryTransition(StructureID*);
     52        static PassRefPtr<StructureID> fromDictionaryTransition(StructureID*);
    5253
    5354        ~StructureID();
     
    6768
    6869    private:
    69         typedef HashMap<RefPtr<UString::Rep>, StructureID*, WTF::IdentifierRepHash, HashTraits<RefPtr<UString::Rep> > > TransitionTable;
     70        typedef HashMap<RefPtr<UString::Rep>, StructureID*, IdentifierRepHash, HashTraits<RefPtr<UString::Rep> > > TransitionTable;
    7071       
    7172        StructureID(JSValue* prototype);
     
    9495        StructureIDChain(StructureID* structureID);
    9596
    96         size_t m_size;
    9797        OwnArrayPtr<RefPtr<StructureID> > m_vector;
    9898    };
  • trunk/JavaScriptCore/kjs/SymbolTable.h

    r36016 r36032  
    119119    };
    120120
    121     typedef HashMap<RefPtr<UString::Rep>, SymbolTableEntry, WTF::IdentifierRepHash, HashTraits<RefPtr<UString::Rep> >, SymbolTableIndexHashTraits> SymbolTable;
     121    typedef HashMap<RefPtr<UString::Rep>, SymbolTableEntry, IdentifierRepHash, HashTraits<RefPtr<UString::Rep> >, SymbolTableIndexHashTraits> SymbolTable;
    122122
    123123} // namespace KJS
  • trunk/JavaScriptCore/kjs/ustring.h

    r36016 r36032  
    337337    }
    338338
     339    struct IdentifierRepHash : PtrHash<RefPtr<KJS::UString::Rep> > {
     340        static unsigned hash(const RefPtr<KJS::UString::Rep>& key) { return key->computedHash(); }
     341        static unsigned hash(KJS::UString::Rep* key) { return key->computedHash(); }
     342    };
     343
    339344} // namespace KJS
    340345
     
    370375    };
    371376
    372     struct IdentifierRepHash : PtrHash<RefPtr<KJS::UString::Rep> > {
    373         static unsigned hash(const RefPtr<KJS::UString::Rep>& key) { return key->computedHash(); }
    374         static unsigned hash(KJS::UString::Rep* key) { return key->computedHash(); }
    375     };
    376 
    377377} // namespace WTF
    378378
Note: See TracChangeset for help on using the changeset viewer.