]> git.saurik.com Git - apple/javascriptcore.git/blame - runtime/JSArray.h
JavaScriptCore-903.5.tar.gz
[apple/javascriptcore.git] / runtime / JSArray.h
CommitLineData
9dae56ea
A
1/*
2 * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
f9bf01c6 3 * Copyright (C) 2003, 2007, 2008, 2009 Apple Inc. All rights reserved.
9dae56ea
A
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 *
19 */
20
21#ifndef JSArray_h
22#define JSArray_h
23
24#include "JSObject.h"
25
14957cd0
A
26#define CHECK_ARRAY_CONSISTENCY 0
27
9dae56ea
A
28namespace JSC {
29
14957cd0 30 typedef HashMap<unsigned, WriteBarrier<Unknown> > SparseArrayValueMap;
9dae56ea 31
14957cd0
A
32 // This struct holds the actual data values of an array. A JSArray object points to it's contained ArrayStorage
33 // struct by pointing to m_vector. To access the contained ArrayStorage struct, use the getStorage() and
34 // setStorage() methods. It is important to note that there may be space before the ArrayStorage that
35 // is used to quick unshift / shift operation. The actual allocated pointer is available by using:
36 // getStorage() - m_indexBias * sizeof(JSValue)
9dae56ea 37 struct ArrayStorage {
14957cd0 38 unsigned m_length; // The "length" property on the array
9dae56ea
A
39 unsigned m_numValuesInVector;
40 SparseArrayValueMap* m_sparseValueMap;
4e4e5a6f 41 void* subclassData; // A JSArray subclass can use this to fill the vector lazily.
14957cd0 42 void* m_allocBase; // Pointer to base address returned by malloc(). Keeping this pointer does eliminate false positives from the leak detector.
f9bf01c6 43 size_t reportedMapCapacity;
14957cd0
A
44#if CHECK_ARRAY_CONSISTENCY
45 bool m_inCompactInitialization;
46#endif
47 WriteBarrier<Unknown> m_vector[1];
9dae56ea
A
48 };
49
14957cd0
A
50 // The CreateCompact creation mode is used for fast construction of arrays
51 // whose size and contents are known at time of creation.
52 //
53 // There are two obligations when using this mode:
54 //
55 // - uncheckedSetIndex() must be used when initializing the array.
56 // - setLength() must be called after initialization.
57
58 enum ArrayCreationMode { CreateCompact, CreateInitialized };
59
60 class JSArray : public JSNonFinalObject {
f9bf01c6 61 friend class Walker;
9dae56ea
A
62
63 public:
14957cd0
A
64 JSArray(VPtrStealingHackType);
65
66 explicit JSArray(JSGlobalData&, Structure*);
67 JSArray(JSGlobalData&, Structure*, unsigned initialLength, ArrayCreationMode);
68 JSArray(JSGlobalData&, Structure*, const ArgList& initialValues);
9dae56ea
A
69 virtual ~JSArray();
70
71 virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
72 virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
f9bf01c6 73 virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
ba379fdc 74 virtual void put(ExecState*, unsigned propertyName, JSValue); // FIXME: Make protected and add setItem.
9dae56ea 75
14957cd0
A
76 static JS_EXPORTDATA const ClassInfo s_info;
77
9dae56ea
A
78 unsigned length() const { return m_storage->m_length; }
79 void setLength(unsigned); // OK to use on new arrays, but not if it might be a RegExpMatchArray.
80
81 void sort(ExecState*);
ba379fdc
A
82 void sort(ExecState*, JSValue compareFunction, CallType, const CallData&);
83 void sortNumeric(ExecState*, JSValue compareFunction, CallType, const CallData&);
9dae56ea 84
ba379fdc
A
85 void push(ExecState*, JSValue);
86 JSValue pop();
9dae56ea 87
14957cd0
A
88 void shiftCount(ExecState*, int count);
89 void unshiftCount(ExecState*, int count);
90
f9bf01c6 91 bool canGetIndex(unsigned i) { return i < m_vectorLength && m_storage->m_vector[i]; }
ba379fdc 92 JSValue getIndex(unsigned i)
9dae56ea
A
93 {
94 ASSERT(canGetIndex(i));
14957cd0 95 return m_storage->m_vector[i].get();
9dae56ea
A
96 }
97
f9bf01c6 98 bool canSetIndex(unsigned i) { return i < m_vectorLength; }
14957cd0 99 void setIndex(JSGlobalData& globalData, unsigned i, JSValue v)
9dae56ea
A
100 {
101 ASSERT(canSetIndex(i));
14957cd0
A
102
103 WriteBarrier<Unknown>& x = m_storage->m_vector[i];
f9bf01c6 104 if (!x) {
14957cd0
A
105 ArrayStorage *storage = m_storage;
106 ++storage->m_numValuesInVector;
107 if (i >= storage->m_length)
108 storage->m_length = i + 1;
f9bf01c6 109 }
14957cd0
A
110 x.set(globalData, this, v);
111 }
112
113 void uncheckedSetIndex(JSGlobalData& globalData, unsigned i, JSValue v)
114 {
115 ASSERT(canSetIndex(i));
116 ArrayStorage *storage = m_storage;
117#if CHECK_ARRAY_CONSISTENCY
118 ASSERT(storage->m_inCompactInitialization);
119#endif
120 storage->m_vector[i].set(globalData, this, v);
9dae56ea
A
121 }
122
ba379fdc
A
123 void fillArgList(ExecState*, MarkedArgumentBuffer&);
124 void copyToRegisters(ExecState*, Register*, uint32_t);
9dae56ea 125
14957cd0 126 static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
9dae56ea 127 {
14957cd0 128 return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
9dae56ea 129 }
f9bf01c6 130
14957cd0
A
131 inline void visitChildrenDirect(SlotVisitor&);
132
133 static ptrdiff_t storageOffset()
134 {
135 return OBJECT_OFFSETOF(JSArray, m_storage);
136 }
137
138 static ptrdiff_t vectorLengthOffset()
139 {
140 return OBJECT_OFFSETOF(JSArray, m_vectorLength);
141 }
9dae56ea
A
142
143 protected:
14957cd0 144 static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesVisitChildren | OverridesGetPropertyNames | JSObject::StructureFlags;
ba379fdc 145 virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
9dae56ea
A
146 virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
147 virtual bool deleteProperty(ExecState*, unsigned propertyName);
f9bf01c6 148 virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&, EnumerationMode mode = ExcludeDontEnumProperties);
14957cd0 149 virtual void visitChildren(SlotVisitor&);
9dae56ea 150
4e4e5a6f
A
151 void* subclassData() const;
152 void setSubclassData(void*);
9dae56ea
A
153
154 private:
9dae56ea 155 bool getOwnPropertySlotSlowCase(ExecState*, unsigned propertyName, PropertySlot&);
ba379fdc 156 void putSlowCase(ExecState*, unsigned propertyName, JSValue);
9dae56ea 157
14957cd0 158 unsigned getNewVectorLength(unsigned desiredLength);
9dae56ea 159 bool increaseVectorLength(unsigned newLength);
14957cd0 160 bool increaseVectorPrefixLength(unsigned newLength);
9dae56ea
A
161
162 unsigned compactForSorting();
163
164 enum ConsistencyCheckType { NormalConsistencyCheck, DestructorConsistencyCheck, SortConsistencyCheck };
165 void checkConsistency(ConsistencyCheckType = NormalConsistencyCheck);
166
14957cd0
A
167 unsigned m_vectorLength; // The valid length of m_vector
168 int m_indexBias; // The number of JSValue sized blocks before ArrayStorage.
169 ArrayStorage *m_storage;
9dae56ea
A
170 };
171
ba379fdc 172 JSArray* asArray(JSValue);
9dae56ea 173
f9bf01c6
A
174 inline JSArray* asArray(JSCell* cell)
175 {
14957cd0 176 ASSERT(cell->inherits(&JSArray::s_info));
f9bf01c6
A
177 return static_cast<JSArray*>(cell);
178 }
9dae56ea 179
ba379fdc 180 inline JSArray* asArray(JSValue value)
9dae56ea 181 {
f9bf01c6
A
182 return asArray(value.asCell());
183 }
184
f9bf01c6 185 inline bool isJSArray(JSGlobalData* globalData, JSCell* cell) { return cell->vptr() == globalData->jsArrayVPtr; }
14957cd0 186 inline bool isJSArray(JSGlobalData* globalData, JSValue v) { return v.isCell() && isJSArray(globalData, v.asCell()); }
f9bf01c6 187
14957cd0 188 inline void JSArray::visitChildrenDirect(SlotVisitor& visitor)
f9bf01c6 189 {
14957cd0 190 JSObject::visitChildrenDirect(visitor);
f9bf01c6
A
191
192 ArrayStorage* storage = m_storage;
193
194 unsigned usedVectorLength = std::min(storage->m_length, m_vectorLength);
14957cd0 195 visitor.appendValues(storage->m_vector, usedVectorLength, MayContainNullValues);
f9bf01c6
A
196
197 if (SparseArrayValueMap* map = storage->m_sparseValueMap) {
198 SparseArrayValueMap::iterator end = map->end();
199 for (SparseArrayValueMap::iterator it = map->begin(); it != end; ++it)
14957cd0 200 visitor.append(&it->second);
f9bf01c6 201 }
9dae56ea
A
202 }
203
14957cd0
A
204 // Rule from ECMA 15.2 about what an array index is.
205 // Must exactly match string form of an unsigned integer, and be less than 2^32 - 1.
206 inline unsigned Identifier::toArrayIndex(bool& ok) const
f9bf01c6 207 {
14957cd0
A
208 unsigned i = toUInt32(ok);
209 if (ok && i >= 0xFFFFFFFFU)
210 ok = false;
211 return i;
f9bf01c6 212 }
ba379fdc 213
9dae56ea
A
214} // namespace JSC
215
216#endif // JSArray_h