Ignore:
Timestamp:
May 9, 2009, 1:35:57 AM (16 years ago)
Author:
[email protected]
Message:

2009-05-09 Maciej Stachowiak <[email protected]>

Reviewed by Gavin Barraclough.


Original patch by John McCall. Updated by Cameron Zwarich. Further refined by me.


  • Assorted speedups to property access


~.3%-1% speedup on SunSpider


1) When we know from the structure ID that an object is using inline storage, plant direct
loads and stores against it; no need to indirect through storage pointer.


2) Also because of the above, union the property storage pointer with the first inline property
slot and add an extra inline property slot.

  • assembler/AbstractMacroAssembler.h: (JSC::AbstractMacroAssembler::CodeLocationInstruction::CodeLocationInstruction): (JSC::AbstractMacroAssembler::CodeLocationInstruction::patchLoadToLEA): (JSC::::CodeLocationCommon::instructionAtOffset):
  • assembler/MacroAssembler.h: (JSC::MacroAssembler::storePtr):
  • assembler/MacroAssemblerX86.h: (JSC::MacroAssemblerX86::store32):
  • assembler/MacroAssemblerX86_64.h: (JSC::MacroAssemblerX86_64::storePtr):
  • assembler/X86Assembler.h: (JSC::X86Assembler::movq_EAXm): (JSC::X86Assembler::movl_rm): (JSC::X86Assembler::patchLoadToLEA):
  • jit/JIT.cpp: (JSC::JIT::privateCompileMainPass):
  • jit/JIT.h:
  • jit/JITPropertyAccess.cpp: (JSC::JIT::compileGetByIdHotPath): (JSC::JIT::compilePutByIdHotPath): (JSC::JIT::compilePutDirectOffset): (JSC::JIT::compileGetDirectOffset): (JSC::JIT::privateCompilePutByIdTransition): (JSC::JIT::patchGetByIdSelf): (JSC::JIT::patchPutByIdReplace): (JSC::JIT::privateCompileGetByIdSelf): (JSC::JIT::privateCompileGetByIdProto): (JSC::JIT::privateCompileGetByIdSelfList): (JSC::JIT::privateCompileGetByIdProtoList): (JSC::JIT::privateCompileGetByIdChainList): (JSC::JIT::privateCompileGetByIdChain): (JSC::JIT::privateCompilePutByIdReplace):
  • runtime/JSObject.cpp: (JSC::JSObject::mark): (JSC::JSObject::removeDirect):
  • runtime/JSObject.h: (JSC::JSObject::propertyStorage): (JSC::JSObject::getDirect): (JSC::JSObject::getOffset): (JSC::JSObject::offsetForLocation): (JSC::JSObject::locationForOffset): (JSC::JSObject::getDirectOffset): (JSC::JSObject::putDirectOffset): (JSC::JSObject::isUsingInlineStorage): (JSC::JSObject::): (JSC::JSObject::JSObject): (JSC::JSObject::~JSObject): (JSC::Structure::isUsingInlineStorage): (JSC::JSObject::putDirect): (JSC::JSObject::putDirectWithoutTransition): (JSC::JSObject::allocatePropertyStorageInline):
  • runtime/Structure.h:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/runtime/JSObject.h

    r43153 r43432  
    5252    };
    5353
    54     typedef JSValue* PropertyStorage;
     54    typedef EncodedJSValue* PropertyStorage;
     55    typedef EncodedJSValue const * ConstPropertyStorage;
    5556
    5657    class JSObject : public JSCell {
     
    7677        Structure* inheritorID();
    7778
    78         PropertyStorage& propertyStorage() { return m_propertyStorage; }
     79        ConstPropertyStorage propertyStorage() const { return (isUsingInlineStorage() ? m_inlineStorage : m_externalStorage); }
     80        PropertyStorage propertyStorage() { return (isUsingInlineStorage() ? m_inlineStorage : m_externalStorage); }
    7981
    8082        virtual UString className() const;
     
    126128        {
    127129            size_t offset = m_structure->get(propertyName);
    128             return offset != WTF::notFound ? m_propertyStorage[offset] : JSValue();
     130            return offset != WTF::notFound ? getDirectOffset(offset) : JSValue();
     131        }
     132
     133        size_t getOffset(const Identifier& propertyName)
     134        {
     135            return m_structure->get(propertyName);
    129136        }
    130137
     
    141148        }
    142149
    143         size_t offsetForLocation(JSValue* location)
    144         {
    145             return location - m_propertyStorage;
     150        size_t offsetForLocation(JSValue* location) const
     151        {
     152            return location - reinterpret_cast<JSValue const *>(propertyStorage());
     153        }
     154
     155        JSValue const * locationForOffset(size_t offset) const
     156        {
     157            return reinterpret_cast<JSValue const *>(&propertyStorage()[offset]);
    146158        }
    147159
    148160        JSValue* locationForOffset(size_t offset)
    149161        {
    150             return &m_propertyStorage[offset];
     162            return reinterpret_cast<JSValue*>(&propertyStorage()[offset]);
    151163        }
    152164
     
    164176
    165177        // Fast access to known property offsets.
    166         JSValue getDirectOffset(size_t offset) { return m_propertyStorage[offset]; }
    167         void putDirectOffset(size_t offset, JSValue value) { m_propertyStorage[offset] = value; }
     178        JSValue getDirectOffset(size_t offset) const { return JSValue::decode(propertyStorage()[offset]); }
     179        void putDirectOffset(size_t offset, JSValue value) { propertyStorage()[offset] = JSValue::encode(value); }
    168180
    169181        void fillGetterPropertySlot(PropertySlot&, JSValue* location);
     
    182194        void allocatePropertyStorage(size_t oldSize, size_t newSize);
    183195        void allocatePropertyStorageInline(size_t oldSize, size_t newSize);
    184         bool usingInlineStorage() const { return m_propertyStorage == m_inlineStorage; }
    185 
    186         static const size_t inlineStorageCapacity = 2;
     196        bool isUsingInlineStorage() const { return m_structure->isUsingInlineStorage(); }
     197
     198        static const size_t inlineStorageCapacity = 3;
    187199        static const size_t nonInlineBaseStorageCapacity = 16;
    188200
     
    203215        RefPtr<Structure> m_inheritorID;
    204216
    205         PropertyStorage m_propertyStorage;       
    206         JSValue m_inlineStorage[inlineStorageCapacity];
     217        union {
     218            PropertyStorage m_externalStorage;
     219            EncodedJSValue m_inlineStorage[inlineStorageCapacity];
     220        };
    207221    };
    208222
     
    219233inline JSObject::JSObject(PassRefPtr<Structure> structure)
    220234    : JSCell(structure.releaseRef()) // ~JSObject balances this ref()
    221     , m_propertyStorage(m_inlineStorage)
    222235{
    223236    ASSERT(m_structure);
     
    230243{
    231244    ASSERT(m_structure);
    232     if (m_propertyStorage != m_inlineStorage)
    233         delete [] m_propertyStorage;
     245    if (!isUsingInlineStorage())
     246        delete [] m_externalStorage;
    234247    m_structure->deref();
    235248}
     
    258271        return m_inheritorID.get();
    259272    return createInheritorID();
     273}
     274
     275inline bool Structure::isUsingInlineStorage() const
     276{
     277    return (propertyStorageCapacity() == JSObject::inlineStorageCapacity);
    260278}
    261279
     
    395413            if (checkReadOnly && currentAttributes & ReadOnly)
    396414                return;
    397             m_propertyStorage[offset] = value;
     415            putDirectOffset(offset, value);
    398416            slot.setExistingProperty(this, offset);
    399417            return;
     
    406424
    407425        ASSERT(offset < m_structure->propertyStorageCapacity());
    408         m_propertyStorage[offset] = value;
     426        putDirectOffset(offset, value);
    409427        slot.setNewProperty(this, offset);
    410428        return;
     
    418436
    419437        ASSERT(offset < structure->propertyStorageCapacity());
    420         m_propertyStorage[offset] = value;
     438        setStructure(structure.release());
     439        putDirectOffset(offset, value);
    421440        slot.setNewProperty(this, offset);
    422441        slot.setWasTransition(true);
    423         setStructure(structure.release());
    424442        return;
    425443    }
     
    430448        if (checkReadOnly && currentAttributes & ReadOnly)
    431449            return;
    432         m_propertyStorage[offset] = value;
     450        putDirectOffset(offset, value);
    433451        slot.setExistingProperty(this, offset);
    434452        return;
     
    440458
    441459    ASSERT(offset < structure->propertyStorageCapacity());
    442     m_propertyStorage[offset] = value;
     460    setStructure(structure.release());
     461    putDirectOffset(offset, value);
    443462    slot.setNewProperty(this, offset);
    444463    slot.setWasTransition(true);
    445     setStructure(structure.release());
    446464}
    447465
     
    452470    if (currentCapacity != m_structure->propertyStorageCapacity())
    453471        allocatePropertyStorage(currentCapacity, m_structure->propertyStorageCapacity());
    454     m_propertyStorage[offset] = value;
     472    putDirectOffset(offset, value);
    455473}
    456474
     
    541559    ASSERT(newSize > oldSize);
    542560
    543     JSValue* oldPropertyStorage = m_propertyStorage;
    544     m_propertyStorage = new JSValue[newSize];
     561    // It's important that this function not rely on m_structure, since
     562    // we might be in the middle of a transition.
     563    bool wasInline = (oldSize == JSObject::inlineStorageCapacity);
     564
     565    PropertyStorage oldPropertyStorage = (wasInline ? m_inlineStorage : m_externalStorage);
     566    PropertyStorage newPropertyStorage = new EncodedJSValue[newSize];
    545567
    546568    for (unsigned i = 0; i < oldSize; ++i)
    547         m_propertyStorage[i] = oldPropertyStorage[i];
    548 
    549     if (oldPropertyStorage != m_inlineStorage)
     569       newPropertyStorage[i] = oldPropertyStorage[i];
     570
     571    if (!wasInline)
    550572        delete [] oldPropertyStorage;
     573
     574    m_externalStorage = newPropertyStorage;
    551575}
    552576
Note: See TracChangeset for help on using the changeset viewer.