Ignore:
Timestamp:
Feb 25, 2009, 3:44:07 PM (16 years ago)
Author:
[email protected]
Message:

JavaScriptCore:

2009-02-25 Geoffrey Garen <[email protected]>

Reviewed by Maciej Stachowiak.


Fixed <rdar://problem/6611174> REGRESSION (r36701): Unable to select
messages on hotmail (24052)


The bug was that for-in enumeration used a cached prototype chain without
validating that it was up-to-date.


This led me to refactor prototype chain caching so it was easier to work
with and harder to get wrong.


After a bit of inlining, this patch is performance-neutral on SunSpider
and the v8 benchmarks.

  • interpreter/Interpreter.cpp: (JSC::Interpreter::tryCachePutByID): (JSC::Interpreter::tryCacheGetByID):
  • jit/JITStubs.cpp: (JSC::JITStubs::tryCachePutByID): (JSC::JITStubs::tryCacheGetByID): (JSC::JITStubs::cti_op_get_by_id_proto_list): Use the new refactored goodness. See lines beginning with "-" and smile.
  • runtime/JSGlobalObject.h: (JSC::Structure::prototypeForLookup): A shout out to const.
  • runtime/JSPropertyNameIterator.h: (JSC::JSPropertyNameIterator::next): We can use a pointer comparison to see if our cached structure chain is equal to the object's structure chain, since in the case of a cache hit, we share references to the same structure chain.
  • runtime/Operations.h: (JSC::countPrototypeChainEntriesAndCheckForProxies): Use the new refactored goodness.
  • runtime/PropertyNameArray.h: (JSC::PropertyNameArray::PropertyNameArray): (JSC::PropertyNameArray::setShouldCache): (JSC::PropertyNameArray::shouldCache): Renamed "cacheable" to "shouldCache" to communicate that the client is specifying a recommendation, not a capability.


  • runtime/Structure.cpp: (JSC::Structure::Structure): No need to initialize a RefPtr. (JSC::Structure::getEnumerablePropertyNames): Moved some code into helper functions.

(JSC::Structure::prototypeChain): New centralized accessor for a prototype
chain. Revalidates on every access, since the objects in the prototype
chain may have mutated.

(JSC::Structure::isValid): Helper function for revalidating a cached
prototype chain.

(JSC::Structure::getEnumerableNamesFromPropertyTable):
(JSC::Structure::getEnumerableNamesFromClassInfoTable): Factored out of
getEnumerablePropertyNames.

  • runtime/Structure.h:
  • runtime/StructureChain.cpp: (JSC::StructureChain::StructureChain):
  • runtime/StructureChain.h: (JSC::StructureChain::create): No need for structureChainsAreEqual, since we use pointer equality now. Refactored StructureChain to make a little more sense and eliminate special cases for null prototypes.

LayoutTests:

2009-02-24 Geoffrey Garen <[email protected]>

Reviewed by Maciej Stachowiak.


Added a test for <rdar://problem/6611174> REGRESSION (r36701): Unable to
select messages on hotmail (24052)

  • fast/js/for-in-cached-expected.txt: Added.
  • fast/js/for-in-cached.html: Added.
  • fast/js/resources/for-in-cached.js: Added. (forIn):
File:
1 edited

Legend:

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

    r41126 r41232  
    330330    }
    331331
    332     inline JSValuePtr Structure::prototypeForLookup(ExecState* exec)
     332    inline JSValuePtr Structure::prototypeForLookup(ExecState* exec) const
    333333    {
    334334        if (typeInfo().type() == ObjectType)
     
    340340        ASSERT(typeInfo().type() == NumberType);
    341341        return exec->lexicalGlobalObject()->numberPrototype();
     342    }
     343
     344    inline StructureChain* Structure::prototypeChain(ExecState* exec) const
     345    {
     346        // We cache our prototype chain so our clients can share it.
     347        if (!isValid(exec, m_cachedPrototypeChain.get())) {
     348            JSValuePtr prototype = prototypeForLookup(exec);
     349            m_cachedPrototypeChain = StructureChain::create(prototype.isNull() ? 0 : asObject(prototype)->structure());
     350        }
     351        return m_cachedPrototypeChain.get();
     352    }
     353
     354    inline bool Structure::isValid(ExecState* exec, StructureChain* cachedPrototypeChain) const
     355    {
     356        if (!cachedPrototypeChain)
     357            return false;
     358
     359        JSValuePtr prototype = prototypeForLookup(exec);
     360        RefPtr<Structure>* cachedStructure = cachedPrototypeChain->head();
     361        while(*cachedStructure && !prototype.isNull()) {
     362            if (asObject(prototype)->structure() != *cachedStructure)
     363                return false;
     364            ++cachedStructure;
     365            prototype = asObject(prototype)->prototype();
     366        }
     367        return prototype.isNull() && !*cachedStructure;
    342368    }
    343369
Note: See TracChangeset for help on using the changeset viewer.