Ignore:
Timestamp:
Aug 20, 2009, 3:36:36 PM (16 years ago)
Author:
[email protected]
Message:

REGRESSION: significant slowdown on Celtic Kane "AJAX declaration" subtest
https://bugs.webkit.org/show_bug.cgi?id=28332

Reviewed by Gavin Barraclough.

The method check optimisation made transitions aware of the value being
assigned when a transition was assigning a function. This had the side
effect of making every assignment of a function expression result in a
new transition, and thus a new Structure. The net result of this is that
the common JS idiom of

function MyObject() {

this.myFunction = function(...){...};

}
new MyObject();

Will produce a unique structure on every iteration, meaning that all
caching is defeated and there is a significant amount of structure churn.

The fix is to return the transition to its original form where it is
keyed off a property name + attributes tuple, but have each transition
support an optional transition on a specific value.

File:
1 edited

Legend:

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

    r44076 r47601  
    11/*
    2  * Copyright (C) 2008 Apple Inc. All rights reserved.
     2 * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    3838
    3939    struct StructureTransitionTableHash {
    40         typedef std::pair<RefPtr<UString::Rep>, std::pair<unsigned, JSCell*> > Key;
     40        typedef std::pair<RefPtr<UString::Rep>, unsigned> Key;
    4141        static unsigned hash(const Key& p)
    4242        {
     
    5454    struct StructureTransitionTableHashTraits {
    5555        typedef WTF::HashTraits<RefPtr<UString::Rep> > FirstTraits;
    56         typedef WTF::GenericHashTraits<unsigned> SecondFirstTraits;
    57         typedef WTF::GenericHashTraits<JSCell*> SecondSecondTraits;
    58         typedef std::pair<FirstTraits::TraitType, std::pair<SecondFirstTraits::TraitType, SecondSecondTraits::TraitType> > TraitType;
     56        typedef WTF::GenericHashTraits<unsigned> SecondTraits;
     57        typedef std::pair<FirstTraits::TraitType, SecondTraits::TraitType > TraitType;
    5958
    60         static const bool emptyValueIsZero = FirstTraits::emptyValueIsZero && SecondFirstTraits::emptyValueIsZero && SecondSecondTraits::emptyValueIsZero;
    61         static TraitType emptyValue() { return std::make_pair(FirstTraits::emptyValue(), std::make_pair(SecondFirstTraits::emptyValue(), SecondSecondTraits::emptyValue())); }
     59        static const bool emptyValueIsZero = FirstTraits::emptyValueIsZero && SecondTraits::emptyValueIsZero;
     60        static TraitType emptyValue() { return std::make_pair(FirstTraits::emptyValue(), SecondTraits::emptyValue()); }
    6261
    63         static const bool needsDestruction = FirstTraits::needsDestruction || SecondFirstTraits::needsDestruction || SecondSecondTraits::needsDestruction;
     62        static const bool needsDestruction = FirstTraits::needsDestruction || SecondTraits::needsDestruction;
    6463
    6564        static void constructDeletedValue(TraitType& slot) { FirstTraits::constructDeletedValue(slot.first); }
     
    6766    };
    6867
    69     typedef HashMap<StructureTransitionTableHash::Key, Structure*, StructureTransitionTableHash, StructureTransitionTableHashTraits> StructureTransitionTable;
     68    class StructureTransitionTable {
     69        typedef std::pair<Structure*, Structure*> Transition;
     70        typedef HashMap<StructureTransitionTableHash::Key, Transition, StructureTransitionTableHash, StructureTransitionTableHashTraits> TransitionTable;
     71    public:
     72        inline bool contains(const StructureTransitionTableHash::Key& key, JSCell* specificValue);
     73        inline Structure* get(const StructureTransitionTableHash::Key& key, JSCell* specificValue) const;
     74        bool hasTransition(const StructureTransitionTableHash::Key& key)
     75        {
     76            return m_table.contains(key);
     77        }
     78        void remove(const StructureTransitionTableHash::Key& key, JSCell* specificValue)
     79        {
     80            TransitionTable::iterator find = m_table.find(key);
     81            if (!specificValue)
     82                find->second.first = 0;
     83            else
     84                find->second.second = 0;
     85            if (!find->second.first && !find->second.second)
     86                m_table.remove(find);
     87        }
     88        void add(const StructureTransitionTableHash::Key& key, Structure* structure, JSCell* specificValue)
     89        {
     90            if (!specificValue) {
     91                TransitionTable::iterator find = m_table.find(key);
     92                if (find == m_table.end())
     93                    m_table.add(key, Transition(structure, 0));
     94                else
     95                    find->second.first = structure;
     96            } else {
     97                // If we're adding a transition to a specific value, then there cannot be
     98                // an existing transition
     99                ASSERT(!m_table.contains(key));
     100                m_table.add(key, Transition(0, structure));
     101            }
     102               
     103
     104        }
     105    private:
     106        TransitionTable m_table;
     107    };
    70108
    71109} // namespace JSC
Note: See TracChangeset for help on using the changeset viewer.