Changeset 48580 in webkit for trunk/JavaScriptCore


Ignore:
Timestamp:
Sep 21, 2009, 7:45:23 AM (16 years ago)
Author:
Adam Roben
Message:

Revert r48573, as it caused many assertion failures

Location:
trunk/JavaScriptCore
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/ChangeLog

    r48578 r48580  
    1818        (JSC::JITThunks::JITThunks):
    1919        * jit/JITStubs.h:
    20 
    21 2009-09-20  Oliver Hunt  <[email protected]>
    22 
    23         Reviewed by Maciej Stachowiak.
    24 
    25         SNES is too slow
    26         https://bugs.webkit.org/show_bug.cgi?id=29534
    27 
    28         The problem was that the emulator used multiple classes with
    29         more properties than our dictionary cutoff allowed, this resulted
    30         in more or less all critical logic inside the emulator requiring
    31         uncached property access.
    32 
    33         Rather than simply bumping the dictionary cutoff, this patch
    34         recognises that there are two ways to create a "dictionary"
    35         structure.  Either by adding a large number of properties, or
    36         by removing a property.  In the case of adding properties we
    37         know all the existing properties will maintain their existing
    38         offsets, so we could cache access to those properties, if we
    39         know they won't be removed.
    40 
    41         To make this possible, this patch adds the logic required to
    42         distinguish a dictionary created by addition from one created
    43         by removal.  With this logic in place we can now cache access
    44         to objects with large numbers of properties.
    45 
    46         SNES performance improved by more than 6x.
    47 
    48         * interpreter/Interpreter.cpp:
    49         (JSC::Interpreter::resolveGlobal):
    50         (JSC::Interpreter::tryCachePutByID):
    51         (JSC::Interpreter::tryCacheGetByID):
    52         * jit/JITStubs.cpp:
    53         (JSC::JITThunks::tryCachePutByID):
    54         (JSC::JITThunks::tryCacheGetByID):
    55         (JSC::DEFINE_STUB_FUNCTION):
    56         * runtime/BatchedTransitionOptimizer.h:
    57         (JSC::BatchedTransitionOptimizer::BatchedTransitionOptimizer):
    58         * runtime/JSObject.cpp:
    59         (JSC::JSObject::removeDirect):
    60         * runtime/Structure.cpp:
    61         (JSC::Structure::Structure):
    62         (JSC::Structure::getEnumerablePropertyNames):
    63         (JSC::Structure::despecifyDictionaryFunction):
    64         (JSC::Structure::addPropertyTransitionToExistingStructure):
    65         (JSC::Structure::addPropertyTransition):
    66         (JSC::Structure::removePropertyTransition):
    67         (JSC::Structure::toDictionaryTransition):
    68         (JSC::Structure::toCacheableDictionaryTransition):
    69         (JSC::Structure::toUncacheableDictionaryTransition):
    70         (JSC::Structure::fromDictionaryTransition):
    71         (JSC::Structure::removePropertyWithoutTransition):
    72         * runtime/Structure.h:
    73         (JSC::Structure::isDictionary):
    74         (JSC::Structure::isUncacheableDictionary):
    75         (JSC::Structure::):
    76         * runtime/StructureChain.cpp:
    77         (JSC::StructureChain::isCacheable):
    7820
    79212009-09-19  Oliver Hunt  <[email protected]>
  • trunk/JavaScriptCore/interpreter/Interpreter.cpp

    r48573 r48580  
    170170    if (globalObject->getPropertySlot(callFrame, ident, slot)) {
    171171        JSValue result = slot.getValue(callFrame, ident);
    172         if (slot.isCacheable() && !globalObject->structure()->isUncacheableDictionary() && slot.slotBase() == globalObject) {
     172        if (slot.isCacheable() && !globalObject->structure()->isDictionary() && slot.slotBase() == globalObject) {
    173173            if (vPC[4].u.structure)
    174174                vPC[4].u.structure->deref();
     
    954954    Structure* structure = baseCell->structure();
    955955
    956     if (structure->isUncacheableDictionary()) {
     956    if (structure->isDictionary()) {
    957957        vPC[0] = getOpcode(op_put_by_id_generic);
    958958        return;
     
    10411041    Structure* structure = asCell(baseValue)->structure();
    10421042
    1043     if (structure->isUncacheableDictionary()) {
     1043    if (structure->isDictionary()) {
    10441044        vPC[0] = getOpcode(op_get_by_id_generic);
    10451045        return;
  • trunk/JavaScriptCore/jit/JITStubs.cpp

    r48574 r48580  
    680680    Structure* structure = baseCell->structure();
    681681
    682     if (structure->isUncacheableDictionary()) {
     682    if (structure->isDictionary()) {
    683683        ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_put_by_id_generic));
    684684        return;
     
    744744    Structure* structure = baseCell->structure();
    745745
    746     if (structure->isUncacheableDictionary()) {
     746    if (structure->isDictionary()) {
    747747        ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_get_by_id_generic));
    748748        return;
     
    11551155    if (baseValue.isCell()
    11561156        && slot.isCacheable()
    1157         && !(structure = asCell(baseValue)->structure())->isUncacheableDictionary()
     1157        && !(structure = asCell(baseValue)->structure())->isDictionary()
    11581158        && (slotBaseObject = asObject(slot.slotBase()))->getPropertySpecificValue(callFrame, ident, specific)
    11591159        && specific
     
    12291229    if (baseValue.isCell()
    12301230        && slot.isCacheable()
    1231         && !asCell(baseValue)->structure()->isUncacheableDictionary()
     1231        && !asCell(baseValue)->structure()->isDictionary()
    12321232        && slot.slotBase() == baseValue) {
    12331233
     
    13001300    CHECK_FOR_EXCEPTION();
    13011301
    1302     if (!baseValue.isCell() || !slot.isCacheable() || asCell(baseValue)->structure()->isUncacheableDictionary()) {
     1302    if (!baseValue.isCell() || !slot.isCacheable() || asCell(baseValue)->structure()->isDictionary()) {
    13031303        ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_fail));
    13041304        return JSValue::encode(result);
     
    21892189    if (globalObject->getPropertySlot(callFrame, ident, slot)) {
    21902190        JSValue result = slot.getValue(callFrame, ident);
    2191         if (slot.isCacheable() && !globalObject->structure()->isUncacheableDictionary() && slot.slotBase() == globalObject) {
     2191        if (slot.isCacheable() && !globalObject->structure()->isDictionary() && slot.slotBase() == globalObject) {
    21922192            GlobalResolveInfo& globalResolveInfo = callFrame->codeBlock()->globalResolveInfo(globalResolveInfoIndex);
    21932193            if (globalResolveInfo.structure)
  • trunk/JavaScriptCore/runtime/BatchedTransitionOptimizer.h

    r48573 r48580  
    3939        {
    4040            if (!m_object->structure()->isDictionary())
    41                 m_object->setStructure(Structure::toCacheableDictionaryTransition(m_object->structure()));
     41                m_object->setStructure(Structure::toDictionaryTransition(m_object->structure()));
    4242        }
    4343
  • trunk/JavaScriptCore/runtime/JSObject.cpp

    r48573 r48580  
    472472{
    473473    size_t offset;
    474     if (m_structure->isUncacheableDictionary()) {
     474    if (m_structure->isDictionary()) {
    475475        offset = m_structure->removePropertyWithoutTransition(propertyName);
    476476        if (offset != WTF::notFound)
  • trunk/JavaScriptCore/runtime/Structure.cpp

    r48573 r48580  
    128128    , m_propertyStorageCapacity(JSObject::inlineStorageCapacity)
    129129    , m_offset(noOffset)
    130     , m_dictionaryKind(NoneDictionaryKind)
     130    , m_isDictionary(false)
    131131    , m_isPinnedPropertyTable(false)
    132132    , m_hasGetterSetterProperties(false)
     
    291291void Structure::getEnumerablePropertyNames(ExecState* exec, PropertyNameArray& propertyNames, JSObject* baseObject)
    292292{
    293     bool shouldCache = propertyNames.shouldCache() && !(propertyNames.size() || isDictionary());
     293    bool shouldCache = propertyNames.shouldCache() && !(propertyNames.size() || m_isDictionary);
    294294
    295295    if (shouldCache && m_cachedPropertyNameArrayData) {
     
    350350    materializePropertyMapIfNecessary();
    351351
    352     ASSERT(isDictionary());
     352    ASSERT(m_isDictionary);
    353353    ASSERT(m_propertyTable);
    354354
     
    392392PassRefPtr<Structure> Structure::addPropertyTransitionToExistingStructure(Structure* structure, const Identifier& propertyName, unsigned attributes, JSCell* specificValue, size_t& offset)
    393393{
    394     ASSERT(!structure->isDictionary());
     394    ASSERT(!structure->m_isDictionary);
    395395    ASSERT(structure->typeInfo().type() == ObjectType);
    396396
     
    406406PassRefPtr<Structure> Structure::addPropertyTransition(Structure* structure, const Identifier& propertyName, unsigned attributes, JSCell* specificValue, size_t& offset)
    407407{
    408     ASSERT(!structure->isDictionary());
     408    ASSERT(!structure->m_isDictionary);
    409409    ASSERT(structure->typeInfo().type() == ObjectType);
    410410    ASSERT(!Structure::addPropertyTransitionToExistingStructure(structure, propertyName, attributes, specificValue, offset));
    411411
    412412    if (structure->transitionCount() > s_maxTransitionLength) {
    413         RefPtr<Structure> transition = toCacheableDictionaryTransition(structure);
     413        RefPtr<Structure> transition = toDictionaryTransition(structure);
    414414        ASSERT(structure != transition);
    415415        offset = transition->put(propertyName, attributes, specificValue);
     
    455455PassRefPtr<Structure> Structure::removePropertyTransition(Structure* structure, const Identifier& propertyName, size_t& offset)
    456456{
    457     ASSERT(!structure->isUncacheableDictionary());
    458 
    459     RefPtr<Structure> transition = toUncacheableDictionaryTransition(structure);
     457    ASSERT(!structure->m_isDictionary);
     458
     459    RefPtr<Structure> transition = toDictionaryTransition(structure);
    460460
    461461    offset = transition->remove(propertyName);
     
    555555}
    556556
    557 PassRefPtr<Structure> Structure::toDictionaryTransition(Structure* structure, DictionaryKind kind)
    558 {
    559     ASSERT(!structure->isDictionary());
    560    
     557PassRefPtr<Structure> Structure::toDictionaryTransition(Structure* structure)
     558{
     559    ASSERT(!structure->m_isDictionary);
     560
    561561    RefPtr<Structure> transition = create(structure->m_prototype, structure->typeInfo());
    562     transition->m_dictionaryKind = kind;
     562    transition->m_isDictionary = true;
    563563    transition->m_propertyStorageCapacity = structure->m_propertyStorageCapacity;
    564564    transition->m_hasGetterSetterProperties = structure->m_hasGetterSetterProperties;
    565    
     565
    566566    structure->materializePropertyMapIfNecessary();
    567567    transition->m_propertyTable = structure->copyPropertyTable();
    568568    transition->m_isPinnedPropertyTable = true;
    569    
     569
    570570    return transition.release();
    571571}
    572572
    573 PassRefPtr<Structure> Structure::toCacheableDictionaryTransition(Structure* structure)
    574 {
    575     return toDictionaryTransition(structure, CachedDictionaryKind);
    576 }
    577 
    578 PassRefPtr<Structure> Structure::toUncacheableDictionaryTransition(Structure* structure)
    579 {
    580     return toDictionaryTransition(structure, UncachedDictionaryKind);
    581 }
    582 
    583573PassRefPtr<Structure> Structure::fromDictionaryTransition(Structure* structure)
    584574{
    585     ASSERT(structure->isDictionary());
     575    ASSERT(structure->m_isDictionary);
    586576
    587577    // Since dictionary Structures are not shared, and no opcodes specialize
     
    592582    // deleted offsets vector) before transitioning from dictionary.
    593583    if (!structure->m_propertyTable || !structure->m_propertyTable->deletedOffsets || structure->m_propertyTable->deletedOffsets->isEmpty())
    594         structure->m_dictionaryKind = NoneDictionaryKind;
     584        structure->m_isDictionary = false;
    595585
    596586    return structure;
     
    611601size_t Structure::removePropertyWithoutTransition(const Identifier& propertyName)
    612602{
    613     ASSERT(isUncacheableDictionary());
     603    ASSERT(m_isDictionary);
    614604
    615605    materializePropertyMapIfNecessary();
  • trunk/JavaScriptCore/runtime/Structure.h

    r48573 r48580  
    7171        static PassRefPtr<Structure> addAnonymousSlotsTransition(Structure*, unsigned count);
    7272        static PassRefPtr<Structure> getterSetterTransition(Structure*);
    73         static PassRefPtr<Structure> toCacheableDictionaryTransition(Structure*);
    74         static PassRefPtr<Structure> toUncacheableDictionaryTransition(Structure*);
     73        static PassRefPtr<Structure> toDictionaryTransition(Structure*);
    7574        static PassRefPtr<Structure> fromDictionaryTransition(Structure*);
    7675
     
    8382        size_t removePropertyWithoutTransition(const Identifier& propertyName);
    8483        void setPrototypeWithoutTransition(JSValue prototype) { m_prototype = prototype; }
    85        
    86         bool isDictionary() const { return m_dictionaryKind != NoneDictionaryKind; }
    87         bool isUncacheableDictionary() const { return m_dictionaryKind == UncachedDictionaryKind; }
     84
     85        bool isDictionary() const { return m_isDictionary; }
    8886
    8987        const TypeInfo& typeInfo() const { return m_typeInfo; }
     
    130128    private:
    131129        Structure(JSValue prototype, const TypeInfo&);
    132        
    133         typedef enum {
    134             NoneDictionaryKind = 0,
    135             CachedDictionaryKind = 1,
    136             UncachedDictionaryKind = 2
    137         } DictionaryKind;
    138         static PassRefPtr<Structure> toDictionaryTransition(Structure*, DictionaryKind);
    139130
    140131        size_t put(const Identifier& propertyName, unsigned attributes, JSCell* specificValue);
     
    197188        signed char m_offset;
    198189
    199         unsigned m_dictionaryKind : 2;
     190        bool m_isDictionary : 1;
    200191        bool m_isPinnedPropertyTable : 1;
    201192        bool m_hasGetterSetterProperties : 1;
  • trunk/JavaScriptCore/runtime/StructureChain.cpp

    r48573 r48580  
    5252   
    5353    while (m_vector[i]) {
    54         // Both classes of dictionary structure may change arbitrarily so we can't cache them
    5554        if (m_vector[i]->isDictionary())
    5655            return false;
Note: See TracChangeset for help on using the changeset viewer.