Bug 20821: Cache property transitions to speed up object initialization
[WebKit-https.git] / JavaScriptCore / kjs / StructureID.h
1 /*
2  * Copyright (C) 2008 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #ifndef StructureID_h
27 #define StructureID_h
28
29 #include "JSType.h"
30 #include "JSValue.h"
31 #include "PropertyMap.h"
32 #include "ustring.h"
33 #include <wtf/HashFunctions.h>
34 #include <wtf/HashTraits.h>
35 #include <wtf/OwnArrayPtr.h>
36 #include <wtf/PassRefPtr.h>
37 #include <wtf/RefCounted.h>
38
39 namespace JSC {
40
41     class JSValue;
42     class StructureIDChain;
43
44     struct TransitionTableHash {
45         typedef std::pair<RefPtr<UString::Rep>, unsigned> TransitionTableKey;
46         static unsigned hash(const TransitionTableKey& p)
47         {
48             return p.first->computedHash();
49         }
50
51         static bool equal(const TransitionTableKey& a, const TransitionTableKey& b)
52         {
53             return a == b;
54         }
55
56         static const bool safeToCompareToEmptyOrDeleted = true;
57     };
58
59     struct TransitionTableHashTraits {
60         typedef WTF::HashTraits<RefPtr<UString::Rep> > FirstTraits;
61         typedef WTF::GenericHashTraits<unsigned> SecondTraits;
62         typedef std::pair<FirstTraits::TraitType, SecondTraits::TraitType> TraitType;
63
64         static const bool emptyValueIsZero = FirstTraits::emptyValueIsZero && SecondTraits::emptyValueIsZero;
65         static TraitType emptyValue() { return std::make_pair(FirstTraits::emptyValue(), SecondTraits::emptyValue()); }
66
67         static const bool needsDestruction = FirstTraits::needsDestruction || SecondTraits::needsDestruction;
68
69         static void constructDeletedValue(TraitType& slot) { FirstTraits::constructDeletedValue(slot.first); }
70         static bool isDeletedValue(const TraitType& value) { return FirstTraits::isDeletedValue(value.first); }
71     };
72
73     class StructureID : public RefCounted<StructureID> {
74     public:
75         friend class CTI;
76         static PassRefPtr<StructureID> create(JSValue* prototype, JSType type = ObjectType)
77         {
78             return adoptRef(new StructureID(prototype, type));
79         }
80
81         static PassRefPtr<StructureID> changePrototypeTransition(StructureID*, JSValue* prototype);
82         static PassRefPtr<StructureID> addPropertyTransition(StructureID*, const Identifier& propertyName, JSValue*, unsigned attributes, JSObject* slotBase, PutPropertySlot&, PropertyStorage&);
83         static PassRefPtr<StructureID> getterSetterTransition(StructureID*);
84         static PassRefPtr<StructureID> toDictionaryTransition(StructureID*);
85         static PassRefPtr<StructureID> fromDictionaryTransition(StructureID*);
86
87         ~StructureID();
88
89         void mark()
90         {
91             if (!m_prototype->marked())
92                 m_prototype->mark();
93         }
94
95         bool isDictionary() const { return m_isDictionary; }
96
97         JSType type() const { return m_type; }
98
99         JSValue* storedPrototype() const { return m_prototype; }
100         JSValue* prototypeForLookup(ExecState*); 
101
102         StructureID* previousID() const { return m_previous.get(); }
103
104         void setCachedPrototypeChain(PassRefPtr<StructureIDChain> cachedPrototypeChain) { m_cachedPrototypeChain = cachedPrototypeChain; }
105         StructureIDChain* cachedPrototypeChain() const { return m_cachedPrototypeChain.get(); }
106
107         const PropertyMap& propertyMap() const { return m_propertyMap; }
108         PropertyMap& propertyMap() { return m_propertyMap; }
109
110         static void transitionTo(StructureID* oldStructureID, StructureID* newStructureID, JSObject* slotBase);
111
112     private:
113         typedef std::pair<RefPtr<UString::Rep>, unsigned> TransitionTableKey;
114         typedef HashMap<TransitionTableKey, StructureID*, TransitionTableHash, TransitionTableHashTraits> TransitionTable;
115
116         StructureID(JSValue* prototype, JSType);
117         
118         static const size_t s_maxTransitionLength = 64;
119
120         bool m_isDictionary;
121         JSType m_type;
122
123         JSValue* m_prototype;
124         RefPtr<StructureIDChain> m_cachedPrototypeChain;
125
126         RefPtr<StructureID> m_previous;
127         UString::Rep* m_nameInPrevious;
128         unsigned m_attributesInPrevious;
129
130         size_t m_transitionCount;
131         TransitionTable m_transitionTable;
132
133         PropertyMap m_propertyMap;
134     };
135
136     class StructureIDChain : public RefCounted<StructureIDChain> {
137     public:
138         static PassRefPtr<StructureIDChain> create(StructureID* structureID) { return adoptRef(new StructureIDChain(structureID)); }
139
140         RefPtr<StructureID>* head() { return m_vector.get(); }
141
142     private:
143         StructureIDChain(StructureID* structureID);
144
145         OwnArrayPtr<RefPtr<StructureID> > m_vector;
146     };
147
148 } // namespace JSC
149
150 #endif // StructureID_h