Changeset 44171 in webkit for trunk/JavaScriptCore


Ignore:
Timestamp:
May 26, 2009, 7:47:35 PM (16 years ago)
Author:
[email protected]
Message:

2009-05-26 Gavin Barraclough <[email protected]>

Reviewed by Oliver Hunt.

Fix for: <rdar://problem/6918095> REGRESSION: jQuery load() issue (25981),
and also an ASSERT failure on http://ihasahotdog.com/.

When overwriting a property on a dictionary with a cached specific value,
clear the cache if new value being written is different.

Export the new symbols.

  • jit/JITStubs.cpp: (JSC::JITStubs::cti_op_get_by_id_method_check_second):

Close dictionary prototypes upon caching a method access, as would happen when caching
a regular get_by_id.

  • runtime/JSObject.h: (JSC::JSObject::propertyStorage): (JSC::JSObject::locationForOffset):

Make these methods private.

(JSC::JSObject::putDirectInternal):

When overwriting a property on a dictionary with a cached specific value,
clear the cache if new value being written is different.

  • runtime/Structure.cpp: (JSC::Structure::despecifyDictionaryFunction):

Reset the specific value field for a given property in a dictionary.

(JSC::Structure::despecifyFunctionTransition):

Rename of 'changeFunctionTransition' (this was already internally refered to as a despecification).

  • runtime/Structure.h:

Declare new method.

Location:
trunk/JavaScriptCore
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/ChangeLog

    r44169 r44171  
     12009-05-26  Gavin Barraclough  <[email protected]>
     2
     3        Reviewed by Oliver Hunt.
     4
     5        Fix for: <rdar://problem/6918095> REGRESSION: jQuery load() issue (25981),
     6        and also an ASSERT failure on http://ihasahotdog.com/.
     7
     8        When overwriting a property on a dictionary with a cached specific value,
     9        clear the cache if new value being written is different.
     10
     11        * JavaScriptCore.exp:
     12            Export the new symbols.
     13        * jit/JITStubs.cpp:
     14        (JSC::JITStubs::cti_op_get_by_id_method_check_second):
     15            Close dictionary prototypes upon caching a method access, as would happen when caching
     16            a regular get_by_id.
     17        * runtime/JSObject.h:
     18        (JSC::JSObject::propertyStorage):
     19        (JSC::JSObject::locationForOffset):
     20            Make these methods private.
     21        (JSC::JSObject::putDirectInternal):
     22            When overwriting a property on a dictionary with a cached specific value,
     23            clear the cache if new value being written is different.
     24        * runtime/Structure.cpp:
     25        (JSC::Structure::despecifyDictionaryFunction):
     26            Reset the specific value field for a given property in a dictionary.
     27        (JSC::Structure::despecifyFunctionTransition):
     28            Rename of 'changeFunctionTransition' (this was already internally refered to as a despecification).
     29        * runtime/Structure.h:
     30            Declare new method.
     31
    1322009-05-26  Gavin Barraclough  <[email protected]>
    233
  • trunk/JavaScriptCore/JavaScriptCore.exp

    r44076 r44171  
    265265__ZN3JSC9Structure21addPropertyTransitionEPS0_RKNS_10IdentifierEjPNS_6JSCellERm
    266266__ZN3JSC9Structure22materializePropertyMapEv
    267 __ZN3JSC9Structure24changeFunctionTransitionEPS0_RKNS_10IdentifierE
    268267__ZN3JSC9Structure25changePrototypeTransitionEPS0_NS_7JSValueE
     268__ZN3JSC9Structure27despecifyDictionaryFunctionERKNS_10IdentifierE
     269__ZN3JSC9Structure27despecifyFunctionTransitionEPS0_RKNS_10IdentifierE
    269270__ZN3JSC9Structure28addPropertyWithoutTransitionERKNS_10IdentifierEjPNS_6JSCellE
    270271__ZN3JSC9Structure3getEPKNS_7UString3RepERjRPNS_6JSCellE
  • trunk/JavaScriptCore/jit/JITStubs.cpp

    r44131 r44171  
    733733    Structure* structure;
    734734    JSCell* specific;
     735    JSObject* slotBaseObject;
    735736    if (baseValue.isCell()
    736737        && slot.isCacheable()
    737738        && !(structure = asCell(baseValue)->structure())->isDictionary()
    738         && asObject(slot.slotBase())->getPropertySpecificValue(callFrame, ident, specific)
     739        && (slotBaseObject = asObject(slot.slotBase()))->getPropertySpecificValue(callFrame, ident, specific)
    739740        && specific
    740741        ) {
    741742
    742743        JSFunction* callee = (JSFunction*)specific;
     744
     745        // Since we're accessing a prototype in a loop, it's a good bet that it
     746        // should not be treated as a dictionary.
     747        if (slotBaseObject->structure()->isDictionary())
     748            slotBaseObject->setStructure(Structure::fromDictionaryTransition(slotBaseObject->structure()));
    743749
    744750        // The result fetched should always be the callee!
     
    748754        // Check to see if the function is on the object's prototype.  Patch up the code to optimize.
    749755        if (slot.slotBase() == structure->prototypeForLookup(callFrame))
    750             JIT::patchMethodCallProto(methodCallLinkInfo, callee, structure, asObject(slot.slotBase()));
     756            JIT::patchMethodCallProto(methodCallLinkInfo, callee, structure, slotBaseObject);
    751757        // Check to see if the function is on the object itself.
    752758        // Since we generate the method-check to check both the structure and a prototype-structure (since this
  • trunk/JavaScriptCore/runtime/JSObject.h

    r44076 r44171  
    8585        Structure* inheritorID();
    8686
    87         ConstPropertyStorage propertyStorage() const { return (isUsingInlineStorage() ? m_inlineStorage : m_externalStorage); }
    88         PropertyStorage propertyStorage() { return (isUsingInlineStorage() ? m_inlineStorage : m_externalStorage); }
    89 
    9087        virtual UString className() const;
    9188
     
    141138        }
    142139
    143         size_t getOffset(const Identifier& propertyName)
    144         {
    145             return m_structure->get(propertyName);
    146         }
    147 
    148140        JSValue* getDirectLocation(const Identifier& propertyName)
    149141        {
     
    164156        }
    165157
    166         const JSValue* locationForOffset(size_t offset) const
    167         {
    168             return reinterpret_cast<const JSValue*>(&propertyStorage()[offset]);
    169         }
    170 
    171         JSValue* locationForOffset(size_t offset)
    172         {
    173             return reinterpret_cast<JSValue*>(&propertyStorage()[offset]);
    174         }
    175 
    176158        void transitionTo(Structure*);
    177159
     
    224206
    225207    private:
     208        ConstPropertyStorage propertyStorage() const { return (isUsingInlineStorage() ? m_inlineStorage : m_externalStorage); }
     209        PropertyStorage propertyStorage() { return (isUsingInlineStorage() ? m_inlineStorage : m_externalStorage); }
     210
     211        const JSValue* locationForOffset(size_t offset) const
     212        {
     213            return reinterpret_cast<const JSValue*>(&propertyStorage()[offset]);
     214        }
     215
     216        JSValue* locationForOffset(size_t offset)
     217        {
     218            return reinterpret_cast<JSValue*>(&propertyStorage()[offset]);
     219        }
     220
    226221        void putDirectInternal(const Identifier& propertyName, JSValue value, unsigned attr, bool checkReadOnly, PutPropertySlot& slot, JSCell*);
    227222        void putDirectInternal(JSGlobalData&, const Identifier& propertyName, JSValue value, unsigned attr, bool checkReadOnly, PutPropertySlot& slot);
     
    427422        size_t offset = m_structure->get(propertyName, currentAttributes, currentSpecificFunction);
    428423        if (offset != WTF::notFound) {
     424            if (currentSpecificFunction && (specificFunction != currentSpecificFunction))
     425                m_structure->despecifyDictionaryFunction(propertyName);
    429426            if (checkReadOnly && currentAttributes & ReadOnly)
    430427                return;
    431428            putDirectOffset(offset, value);
    432             slot.setExistingProperty(this, offset);
     429            if (!specificFunction && !currentSpecificFunction)
     430                slot.setExistingProperty(this, offset);
    433431            return;
    434432        }
     
    470468
    471469        if (currentSpecificFunction && (specificFunction != currentSpecificFunction)) {
    472             setStructure(Structure::changeFunctionTransition(m_structure, propertyName));
     470            setStructure(Structure::despecifyFunctionTransition(m_structure, propertyName));
    473471            putDirectOffset(offset, value);
    474472            // Function transitions are not currently cachable, so leave the slot in an uncachable state.
  • trunk/JavaScriptCore/runtime/Structure.cpp

    r44076 r44171  
    328328}
    329329
     330void Structure::despecifyDictionaryFunction(const Identifier& propertyName)
     331{
     332    const UString::Rep* rep = propertyName._ustring.rep();
     333
     334    materializePropertyMapIfNecessary();
     335
     336    ASSERT(m_isDictionary);
     337    ASSERT(m_propertyTable);
     338
     339    unsigned i = rep->computedHash();
     340
     341#if DUMP_PROPERTYMAP_STATS
     342    ++numProbes;
     343#endif
     344
     345    unsigned entryIndex = m_propertyTable->entryIndices[i & m_propertyTable->sizeMask];
     346    ASSERT(entryIndex != emptyEntryIndex);
     347
     348    if (rep == m_propertyTable->entries()[entryIndex - 1].key) {
     349        m_propertyTable->entries()[entryIndex - 1].specificValue = 0;
     350        return;
     351    }
     352
     353#if DUMP_PROPERTYMAP_STATS
     354    ++numCollisions;
     355#endif
     356
     357    unsigned k = 1 | doubleHash(rep->computedHash());
     358
     359    while (1) {
     360        i += k;
     361
     362#if DUMP_PROPERTYMAP_STATS
     363        ++numRehashes;
     364#endif
     365
     366        entryIndex = m_propertyTable->entryIndices[i & m_propertyTable->sizeMask];
     367        ASSERT(entryIndex != emptyEntryIndex);
     368
     369        if (rep == m_propertyTable->entries()[entryIndex - 1].key) {
     370            m_propertyTable->entries()[entryIndex - 1].specificValue = 0;
     371            return;
     372        }
     373    }
     374}
     375
    330376PassRefPtr<Structure> Structure::addPropertyTransitionToExistingStructure(Structure* structure, const Identifier& propertyName, unsigned attributes, JSCell* specificValue, size_t& offset)
    331377{
     
    441487}
    442488
    443 PassRefPtr<Structure> Structure::changeFunctionTransition(Structure* structure, const Identifier& replaceFunction)
     489PassRefPtr<Structure> Structure::despecifyFunctionTransition(Structure* structure, const Identifier& replaceFunction)
    444490{
    445491    RefPtr<Structure> transition = create(structure->storedPrototype(), structure->typeInfo());
  • trunk/JavaScriptCore/runtime/Structure.h

    r44076 r44171  
    6666        static PassRefPtr<Structure> removePropertyTransition(Structure*, const Identifier& propertyName, size_t& offset);
    6767        static PassRefPtr<Structure> changePrototypeTransition(Structure*, JSValue prototype);
    68         static PassRefPtr<Structure> changeFunctionTransition(Structure*, const Identifier&);       
     68        static PassRefPtr<Structure> despecifyFunctionTransition(Structure*, const Identifier&);       
    6969        static PassRefPtr<Structure> getterSetterTransition(Structure*);
    7070        static PassRefPtr<Structure> toDictionaryTransition(Structure*);
     
    115115
    116116        JSCell* specificValue() { return m_specificValueInPrevious; }
     117        void despecifyDictionaryFunction(const Identifier& propertyName);
    117118
    118119    private:
Note: See TracChangeset for help on using the changeset viewer.