2008-09-15 Maciej Stachowiak <mjs@apple.com>
[WebKit.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 PropertyNameArray;
43     class StructureIDChain;
44
45     struct TransitionTableHash {
46         typedef std::pair<RefPtr<UString::Rep>, unsigned> TransitionTableKey;
47         static unsigned hash(const TransitionTableKey& p)
48         {
49             return p.first->computedHash();
50         }
51
52         static bool equal(const TransitionTableKey& a, const TransitionTableKey& b)
53         {
54             return a == b;
55         }
56
57         static const bool safeToCompareToEmptyOrDeleted = true;
58     };
59
60     struct TransitionTableHashTraits {
61         typedef WTF::HashTraits<RefPtr<UString::Rep> > FirstTraits;
62         typedef WTF::GenericHashTraits<unsigned> SecondTraits;
63         typedef std::pair<FirstTraits::TraitType, SecondTraits::TraitType> TraitType;
64
65         static const bool emptyValueIsZero = FirstTraits::emptyValueIsZero && SecondTraits::emptyValueIsZero;
66         static TraitType emptyValue() { return std::make_pair(FirstTraits::emptyValue(), SecondTraits::emptyValue()); }
67
68         static const bool needsDestruction = FirstTraits::needsDestruction || SecondTraits::needsDestruction;
69
70         static void constructDeletedValue(TraitType& slot) { FirstTraits::constructDeletedValue(slot.first); }
71         static bool isDeletedValue(const TraitType& value) { return FirstTraits::isDeletedValue(value.first); }
72     };
73
74     class StructureID : public RefCounted<StructureID> {
75     public:
76         friend class CTI;
77         static PassRefPtr<StructureID> create(JSValue* prototype, JSType type = ObjectType)
78         {
79             return adoptRef(new StructureID(prototype, type));
80         }
81
82         static PassRefPtr<StructureID> changePrototypeTransition(StructureID*, JSValue* prototype);
83         static PassRefPtr<StructureID> addPropertyTransition(StructureID*, const Identifier& propertyName, JSValue*, unsigned attributes, JSObject* slotBase, PutPropertySlot&, PropertyStorage&);
84         static PassRefPtr<StructureID> getterSetterTransition(StructureID*);
85         static PassRefPtr<StructureID> toDictionaryTransition(StructureID*);
86         static PassRefPtr<StructureID> fromDictionaryTransition(StructureID*);
87
88         ~StructureID();
89
90         void mark()
91         {
92             if (!m_prototype->marked())
93                 m_prototype->mark();
94         }
95
96         bool isDictionary() const { return m_isDictionary; }
97
98         JSType type() const { return m_type; }
99
100         JSValue* storedPrototype() const { return m_prototype; }
101         JSValue* prototypeForLookup(ExecState*); 
102
103         StructureID* previousID() const { return m_previous.get(); }
104
105         void setCachedPrototypeChain(PassRefPtr<StructureIDChain> cachedPrototypeChain) { m_cachedPrototypeChain = cachedPrototypeChain; }
106         StructureIDChain* cachedPrototypeChain() const { return m_cachedPrototypeChain.get(); }
107
108         const PropertyMap& propertyMap() const { return m_propertyMap; }
109         PropertyMap& propertyMap() { return m_propertyMap; }
110
111         void getEnumerablePropertyNames(PropertyNameArray&) const;
112
113         static void transitionTo(StructureID* oldStructureID, StructureID* newStructureID, JSObject* slotBase);
114
115         void clearEnumerationCache() { m_cachedPropertyNameArray.clear(); }
116
117     private:
118         typedef std::pair<RefPtr<UString::Rep>, unsigned> TransitionTableKey;
119         typedef HashMap<TransitionTableKey, StructureID*, TransitionTableHash, TransitionTableHashTraits> TransitionTable;
120
121         StructureID(JSValue* prototype, JSType);
122         
123         static const size_t s_maxTransitionLength = 64;
124
125         bool m_isDictionary;
126         JSType m_type;
127
128         JSValue* m_prototype;
129         RefPtr<StructureIDChain> m_cachedPrototypeChain;
130
131         RefPtr<StructureID> m_previous;
132         UString::Rep* m_nameInPrevious;
133         unsigned m_attributesInPrevious;
134
135         size_t m_transitionCount;
136         TransitionTable m_transitionTable;
137
138         mutable Vector<UString::Rep*> m_cachedPropertyNameArray;
139
140         PropertyMap m_propertyMap;
141     };
142
143     class StructureIDChain : public RefCounted<StructureIDChain> {
144     public:
145         static PassRefPtr<StructureIDChain> create(StructureID* structureID) { return adoptRef(new StructureIDChain(structureID)); }
146
147         RefPtr<StructureID>* head() { return m_vector.get(); }
148
149     private:
150         StructureIDChain(StructureID* structureID);
151
152         OwnArrayPtr<RefPtr<StructureID> > m_vector;
153     };
154
155 } // namespace JSC
156
157 #endif // StructureID_h