source: webkit/trunk/JavaScriptCore/kjs/StructureID.h@ 37370

Last change on this file since 37370 was 37370, checked in by [email protected], 17 years ago

2008-10-06 Sam Weinig <[email protected]>

Reviewed by Cameron Zwarich.

Fix for https://bugs.webkit.org/show_bug.cgi?id=21415
Improve the division between PropertyStorageArray and PropertyMap

  • Rework ProperyMap to store offsets in the value so that they don't change when rehashing. This allows us not to have to keep the PropertyStorageArray in sync and thus not have to pass it in.
  • Rename PropertyMap::getOffset -> PropertyMap::get since put/remove now also return offsets.
  • A Vector of deleted offsets is now needed since the storage is out of band.

1% win on SunSpider. Wash on V8 suite.

  • JavaScriptCore.exp:
  • VM/CTI.cpp: (JSC::transitionWillNeedStorageRealloc):
  • VM/Machine.cpp: (JSC::Machine::privateExecute): Transition logic can be greatly simplified by the fact that the storage capacity is always known, and is correct for the inline case.
  • kjs/JSObject.cpp: (JSC::JSObject::put): Rename getOffset -> get. (JSC::JSObject::deleteProperty): Ditto. (JSC::JSObject::getPropertyAttributes): Ditto. (JSC::JSObject::removeDirect): Use returned offset to clear the value in the PropertyNameArray. (JSC::JSObject::allocatePropertyStorage): Add assert.
  • kjs/JSObject.h: (JSC::JSObject::getDirect): Rename getOffset -> get (JSC::JSObject::getDirectLocation): Rename getOffset -> get (JSC::JSObject::putDirect): Use propertyStorageCapacity to determine whether or not to resize. Also, since put now returns an offset (and thus addPropertyTransition does also) setting of the PropertyStorageArray is now done here. (JSC::JSObject::transitionTo):
  • kjs/PropertyMap.cpp: (JSC::PropertyMap::checkConsistency): PropertyStorageArray is no longer passed in. (JSC::PropertyMap::operator=): Copy the delete offsets vector. (JSC::PropertyMap::put): Instead of setting the PropertyNameArray explicitly, return the offset where the value should go. (JSC::PropertyMap::remove): Instead of removing from the PropertyNameArray explicitly, return the offset where the value should be removed. (JSC::PropertyMap::get): Switch to using the stored offset, instead of the implicit one. (JSC::PropertyMap::insert): (JSC::PropertyMap::expand): This is never called when m_table is null, so remove that branch and add it as an assertion. (JSC::PropertyMap::createTable): Consistency checks no longer take a PropertyNameArray. (JSC::PropertyMap::rehash): No need to rehash the PropertyNameArray now that it is completely out of band.
  • kjs/PropertyMap.h: (JSC::PropertyMapEntry::PropertyMapEntry): Store offset into PropertyNameArray. (JSC::PropertyMap::get): Switch to using the stored offset, instead of the implicit one.
  • kjs/StructureID.cpp: (JSC::StructureID::StructureID): Initialize the propertyStorageCapacity to JSObject::inlineStorageCapacity. (JSC::StructureID::growPropertyStorageCapacity): Grow the storage capacity as described below. (JSC::StructureID::addPropertyTransition): Copy the storage capacity. (JSC::StructureID::toDictionaryTransition): Ditto. (JSC::StructureID::changePrototypeTransition): Ditto. (JSC::StructureID::getterSetterTransition): Ditto.
  • kjs/StructureID.h: (JSC::StructureID::propertyStorageCapacity): Add propertyStorageCapacity which is the current capacity for the JSObjects PropertyStorageArray. It starts at the JSObject::inlineStorageCapacity (currently 2), then when it first needs to be resized moves to the JSObject::nonInlineBaseStorageCapacity (currently 16), and after that doubles each time.
File size: 6.5 KB
Line 
1// -*- mode: c++; c-basic-offset: 4 -*-
2/*
3 * Copyright (C) 2008 Apple Inc. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#ifndef StructureID_h
28#define StructureID_h
29
30#include "JSType.h"
31#include "JSValue.h"
32#include "PropertyMap.h"
33#include "TypeInfo.h"
34#include "ustring.h"
35#include <wtf/HashFunctions.h>
36#include <wtf/HashTraits.h>
37#include <wtf/OwnArrayPtr.h>
38#include <wtf/PassRefPtr.h>
39#include <wtf/RefCounted.h>
40
41namespace JSC {
42
43 class JSValue;
44 class PropertyNameArray;
45 class PropertyNameArrayData;
46 class StructureIDChain;
47
48 struct TransitionTableHash {
49 typedef std::pair<RefPtr<UString::Rep>, unsigned> TransitionTableKey;
50 static unsigned hash(const TransitionTableKey& p)
51 {
52 return p.first->computedHash();
53 }
54
55 static bool equal(const TransitionTableKey& a, const TransitionTableKey& b)
56 {
57 return a == b;
58 }
59
60 static const bool safeToCompareToEmptyOrDeleted = true;
61 };
62
63 struct TransitionTableHashTraits {
64 typedef WTF::HashTraits<RefPtr<UString::Rep> > FirstTraits;
65 typedef WTF::GenericHashTraits<unsigned> SecondTraits;
66 typedef std::pair<FirstTraits::TraitType, SecondTraits::TraitType> TraitType;
67
68 static const bool emptyValueIsZero = FirstTraits::emptyValueIsZero && SecondTraits::emptyValueIsZero;
69 static TraitType emptyValue() { return std::make_pair(FirstTraits::emptyValue(), SecondTraits::emptyValue()); }
70
71 static const bool needsDestruction = FirstTraits::needsDestruction || SecondTraits::needsDestruction;
72
73 static void constructDeletedValue(TraitType& slot) { FirstTraits::constructDeletedValue(slot.first); }
74 static bool isDeletedValue(const TraitType& value) { return FirstTraits::isDeletedValue(value.first); }
75 };
76
77 class StructureID : public RefCounted<StructureID> {
78 public:
79 friend class CTI;
80 static PassRefPtr<StructureID> create(JSValue* prototype, const TypeInfo& typeInfo)
81 {
82 return adoptRef(new StructureID(prototype, typeInfo));
83 }
84
85 static PassRefPtr<StructureID> changePrototypeTransition(StructureID*, JSValue* prototype);
86 static PassRefPtr<StructureID> addPropertyTransition(StructureID*, const Identifier& propertyName, unsigned attributes, size_t& offset);
87 static PassRefPtr<StructureID> getterSetterTransition(StructureID*);
88 static PassRefPtr<StructureID> toDictionaryTransition(StructureID*);
89 static PassRefPtr<StructureID> fromDictionaryTransition(StructureID*);
90
91 ~StructureID();
92
93 void mark()
94 {
95 if (!m_prototype->marked())
96 m_prototype->mark();
97 }
98
99 bool isDictionary() const { return m_isDictionary; }
100
101 const TypeInfo& typeInfo() const { return m_typeInfo; }
102
103 // For use when first creating a new structure.
104 TypeInfo& mutableTypeInfo() { return m_typeInfo; }
105
106 JSValue* storedPrototype() const { return m_prototype; }
107 JSValue* prototypeForLookup(ExecState*);
108
109 StructureID* previousID() const { return m_previous.get(); }
110
111 StructureIDChain* createCachedPrototypeChain();
112 void setCachedPrototypeChain(PassRefPtr<StructureIDChain> cachedPrototypeChain) { m_cachedPrototypeChain = cachedPrototypeChain; }
113 StructureIDChain* cachedPrototypeChain() const { return m_cachedPrototypeChain.get(); }
114
115 const PropertyMap& propertyMap() const { return m_propertyMap; }
116 PropertyMap& propertyMap() { return m_propertyMap; }
117
118 void setCachedTransistionOffset(size_t offset) { m_cachedTransistionOffset = offset; }
119 size_t cachedTransistionOffset() const { return m_cachedTransistionOffset; }
120
121 void growPropertyStorageCapacity();
122 size_t propertyStorageCapacity() const { return m_propertyStorageCapacity; }
123
124 void getEnumerablePropertyNames(ExecState*, PropertyNameArray&, JSObject*);
125 void clearEnumerationCache();
126
127 private:
128 typedef std::pair<RefPtr<UString::Rep>, unsigned> TransitionTableKey;
129 typedef HashMap<TransitionTableKey, StructureID*, TransitionTableHash, TransitionTableHashTraits> TransitionTable;
130
131 StructureID(JSValue* prototype, const TypeInfo&);
132
133 static const size_t s_maxTransitionLength = 64;
134
135 TypeInfo m_typeInfo;
136
137 bool m_isDictionary;
138
139 JSValue* m_prototype;
140 RefPtr<StructureIDChain> m_cachedPrototypeChain;
141
142 RefPtr<StructureID> m_previous;
143 UString::Rep* m_nameInPrevious;
144 unsigned m_attributesInPrevious;
145
146 size_t m_transitionCount;
147 TransitionTable m_transitionTable;
148
149 RefPtr<PropertyNameArrayData> m_cachedPropertyNameArrayData;
150
151 PropertyMap m_propertyMap;
152 size_t m_propertyStorageCapacity;
153
154 size_t m_cachedTransistionOffset;
155 };
156
157 class StructureIDChain : public RefCounted<StructureIDChain> {
158 public:
159 static PassRefPtr<StructureIDChain> create(StructureID* structureID) { return adoptRef(new StructureIDChain(structureID)); }
160
161 RefPtr<StructureID>* head() { return m_vector.get(); }
162
163 private:
164 StructureIDChain(StructureID* structureID);
165
166 OwnArrayPtr<RefPtr<StructureID> > m_vector;
167 };
168
169 bool structureIDChainsAreEqual(StructureIDChain*, StructureIDChain*);
170
171} // namespace JSC
172
173#endif // StructureID_h
Note: See TracBrowser for help on using the repository browser.