Changeset 45039 in webkit


Ignore:
Timestamp:
Jun 23, 2009 7:47:48 PM (15 years ago)
Author:
oliver@apple.com
Message:

<rdar://problem/6992806> REGRESSION: Enumeration can skip new properties in cases of prototypes that have more than 64 (26593)
<https://bugs.webkit.org/show_bug.cgi?id=26593>

Reviewed by Gavin Barraclough.

Add tests to ensure we correctly invalidate caching that depends on structure chains
that include dictionaries.

Location:
trunk
Files:
2 added
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/ChangeLog

    r45011 r45039  
     12009-06-23  Oliver Hunt  <oliver@apple.com>
     2
     3        Reviewed by Gavin Barraclough.
     4
     5        <rdar://problem/6992806> REGRESSION: Enumeration can skip new properties in cases of prototypes that have more than 64 (26593)
     6        <https://bugs.webkit.org/show_bug.cgi?id=26593>
     7
     8        Do not attempt to cache structure chains if they contain a dictionary at any level.
     9
     10        * interpreter/Interpreter.cpp:
     11        (JSC::Interpreter::tryCachePutByID):
     12        (JSC::Interpreter::tryCacheGetByID):
     13        * jit/JITStubs.cpp:
     14        (JSC::JITThunks::tryCachePutByID):
     15        * runtime/Structure.cpp:
     16        (JSC::Structure::getEnumerablePropertyNames):
     17        (JSC::Structure::addPropertyTransition):
     18        * runtime/StructureChain.cpp:
     19        (JSC::StructureChain::isCacheable):
     20        * runtime/StructureChain.h:
     21
    1222009-06-23  Yong Li  <yong.li@torchmobile.com>
    223
  • trunk/JavaScriptCore/interpreter/Interpreter.cpp

    r44923 r45039  
    971971    }
    972972
     973    StructureChain* protoChain = structure->prototypeChain(callFrame);
     974    if (!protoChain->isCacheable()) {
     975        vPC[0] = getOpcode(op_put_by_id_generic);
     976        return;
     977    }
     978
    973979    // Structure transition, cache transition info
    974980    if (slot.type() == PutPropertySlot::NewProperty) {
     
    976982        vPC[4] = structure->previousID();
    977983        vPC[5] = structure;
    978         vPC[6] = structure->prototypeChain(callFrame);
     984        vPC[6] = protoChain;
    979985        vPC[7] = slot.cachedOffset();
    980986        codeBlock->refStructures(vPC);
     
    10781084    }
    10791085
     1086    StructureChain* protoChain = structure->prototypeChain(callFrame);
     1087    if (!protoChain->isCacheable()) {
     1088        vPC[0] = getOpcode(op_put_by_id_generic);
     1089        return;
     1090    }
     1091
    10801092    vPC[0] = getOpcode(op_get_by_id_chain);
    10811093    vPC[4] = structure;
    1082     vPC[5] = structure->prototypeChain(callFrame);
     1094    vPC[5] = protoChain;
    10831095    vPC[6] = count;
    10841096    vPC[7] = slot.cachedOffset();
  • trunk/JavaScriptCore/jit/JITStubs.cpp

    r44889 r45039  
    384384    if (slot.type() == PutPropertySlot::NewProperty) {
    385385        StructureChain* prototypeChain = structure->prototypeChain(callFrame);
     386        if (!prototypeChain->isCacheable()) {
     387            ctiPatchCallByReturnAddress(returnAddress, FunctionPtr(JITStubs::cti_op_put_by_id_generic));
     388            return;
     389        }
    386390        stubInfo->initPutByIdTransition(structure->previousID(), structure, prototypeChain);
    387391        JIT::compilePutByIdTransition(callFrame->scopeChain()->globalData, codeBlock, stubInfo, structure->previousID(), structure, slot.cachedOffset(), prototypeChain, returnAddress);
     
    471475
    472476    StructureChain* prototypeChain = structure->prototypeChain(callFrame);
     477    if (!prototypeChain->isCacheable()) {
     478        ctiPatchCallByReturnAddress(returnAddress, FunctionPtr(JITStubs::cti_op_get_by_id_generic));
     479        return;
     480    }
    473481    stubInfo->initGetByIdChain(structure, prototypeChain);
    474482    JIT::compileGetByIdChain(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, structure, prototypeChain, count, slot.cachedOffset(), returnAddress);
     
    10441052            ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_list_full));
    10451053    } else if (size_t count = countPrototypeChainEntriesAndCheckForProxies(callFrame, baseValue, slot)) {
     1054        StructureChain* protoChain = structure->prototypeChain(callFrame);
     1055        if (!protoChain->isCacheable()) {
     1056            ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_fail));
     1057            return JSValue::encode(result);
     1058        }
     1059       
    10461060        int listIndex;
    10471061        PolymorphicAccessStructureList* prototypeStructureList = getPolymorphicAccessStructureListSlot(stubInfo, listIndex);
    1048         JIT::compileGetByIdChainList(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, prototypeStructureList, listIndex, structure, structure->prototypeChain(callFrame), count, slot.cachedOffset());
     1062        JIT::compileGetByIdChainList(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, prototypeStructureList, listIndex, structure, protoChain, count, slot.cachedOffset());
    10491063
    10501064        if (listIndex == (POLYMORPHIC_LIST_CACHE_SIZE - 1))
  • trunk/JavaScriptCore/runtime/Structure.cpp

    r44171 r45039  
    307307
    308308    if (shouldCache) {
     309        StructureChain* protoChain = prototypeChain(exec);
    309310        m_cachedPropertyNameArrayData = propertyNames.data();
    310         m_cachedPropertyNameArrayData->setCachedPrototypeChain(prototypeChain(exec));
     311        if (!protoChain->isCacheable())
     312            return;
     313        m_cachedPropertyNameArrayData->setCachedPrototypeChain(protoChain);
    311314        m_cachedPropertyNameArrayData->setCachedStructure(this);
    312315    }
     
    408411    if (structure->transitionCount() > s_maxTransitionLength) {
    409412        RefPtr<Structure> transition = toDictionaryTransition(structure);
     413        ASSERT(structure != transition);
    410414        offset = transition->put(propertyName, attributes, specificValue);
    411415        if (transition->propertyStorageSize() > transition->propertyStorageCapacity())
  • trunk/JavaScriptCore/runtime/StructureChain.cpp

    r44224 r45039  
    4747}
    4848
     49bool StructureChain::isCacheable() const
     50{
     51    uint32_t i = 0;
     52   
     53    while (m_vector[i]) {
     54        if (m_vector[i++]->isDictionary())
     55            return false;
     56    }
     57    return true;
     58}
     59
    4960} // namespace JSC
  • trunk/JavaScriptCore/runtime/StructureChain.h

    r44224 r45039  
    4040        static PassRefPtr<StructureChain> create(Structure* head) { return adoptRef(new StructureChain(head)); }
    4141        RefPtr<Structure>* head() { return m_vector.get(); }
     42        bool isCacheable() const;
    4243
    4344    private:
  • trunk/LayoutTests/ChangeLog

    r45027 r45039  
     12009-06-23  Oliver Hunt  <oliver@apple.com>
     2
     3        Reviewed by Gavin Barraclough.
     4
     5        <rdar://problem/6992806> REGRESSION: Enumeration can skip new properties in cases of prototypes that have more than 64 (26593)
     6        <https://bugs.webkit.org/show_bug.cgi?id=26593>
     7
     8        Add tests to ensure we correctly invalidate caching that depends on structure chains
     9        that include dictionaries.
     10
     11        * fast/js/dictionary-no-cache.html: Added.
     12        * fast/js/dictionary-no-cache-expected.txt: Added.
     13        * fast/js/resources/dictionary-no-cache.js: Added.
     14
    1152009-06-23  Ojan Vafai  <ojan@chromium.org>
    216
Note: See TracChangeset for help on using the changeset viewer.