tizen beta release
[framework/web/webkit-efl.git] / Source / JavaScriptCore / runtime / JSArray.h
1 /*
2  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
3  *  Copyright (C) 2003, 2007, 2008, 2009 Apple Inc. All rights reserved.
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
26 #define CHECK_ARRAY_CONSISTENCY 0
27
28 namespace JSC {
29
30     typedef HashMap<unsigned, WriteBarrier<Unknown> > SparseArrayValueMap;
31
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)
37     struct ArrayStorage {
38         unsigned m_length; // The "length" property on the array
39         unsigned m_numValuesInVector;
40         SparseArrayValueMap* m_sparseValueMap;
41         void* subclassData; // A JSArray subclass can use this to fill the vector lazily.
42         void* m_allocBase; // Pointer to base address returned by malloc().  Keeping this pointer does eliminate false positives from the leak detector.
43         size_t reportedMapCapacity;
44 #if CHECK_ARRAY_CONSISTENCY
45         bool m_inCompactInitialization;
46 #endif
47         WriteBarrier<Unknown> m_vector[1];
48     };
49
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 {
61         friend class Walker;
62
63     protected:
64         explicit JSArray(JSGlobalData&, Structure*);
65
66         void finishCreation(JSGlobalData&);
67         void finishCreation(JSGlobalData&, unsigned initialLength, ArrayCreationMode);
68         void finishCreation(JSGlobalData&, const ArgList&);
69         void finishCreation(JSGlobalData&, const JSValue*, size_t length);
70     
71     public:
72         typedef JSNonFinalObject Base;
73
74         JSArray(VPtrStealingHackType);
75         virtual ~JSArray();
76
77         static JSArray* create(JSGlobalData& globalData, Structure* structure)
78         {
79             JSArray* array = new (allocateCell<JSArray>(globalData.heap)) JSArray(globalData, structure);
80             array->finishCreation(globalData);
81             return array;
82         }
83
84         static JSArray* create(JSGlobalData& globalData, Structure* structure, unsigned initialLength, ArrayCreationMode createMode)
85         {
86             JSArray* array = new (allocateCell<JSArray>(globalData.heap)) JSArray(globalData, structure);
87             array->finishCreation(globalData, initialLength, createMode);
88             return array;
89         }
90
91         static JSArray* create(JSGlobalData& globalData, Structure* structure, const ArgList& initialValues)
92         {
93             JSArray* array = new (allocateCell<JSArray>(globalData.heap)) JSArray(globalData, structure);
94             array->finishCreation(globalData, initialValues);
95             return array;
96         }
97
98         static JSArray* create(JSGlobalData& globalData, Structure* structure, const JSValue* values, size_t length)
99         {
100             JSArray* array = new (allocateCell<JSArray>(globalData.heap)) JSArray(globalData, structure);
101             array->finishCreation(globalData, values, length);
102             return array;
103         }
104
105         static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier& propertyName, PropertySlot&);
106         static bool getOwnPropertySlotByIndex(JSCell*, ExecState*, unsigned propertyName, PropertySlot&);
107         static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&);
108         static void putByIndex(JSCell*, ExecState*, unsigned propertyName, JSValue);
109
110         static JS_EXPORTDATA const ClassInfo s_info;
111         
112         unsigned length() const { return m_storage->m_length; }
113         void setLength(unsigned); // OK to use on new arrays, but not if it might be a RegExpMatchArray.
114
115         void sort(ExecState*);
116         void sort(ExecState*, JSValue compareFunction, CallType, const CallData&);
117         void sortNumeric(ExecState*, JSValue compareFunction, CallType, const CallData&);
118
119         void push(ExecState*, JSValue);
120         JSValue pop();
121
122         void shiftCount(ExecState*, int count);
123         void unshiftCount(ExecState*, int count);
124
125         bool canGetIndex(unsigned i) { return i < m_vectorLength && m_storage->m_vector[i]; }
126         JSValue getIndex(unsigned i)
127         {
128             ASSERT(canGetIndex(i));
129             return m_storage->m_vector[i].get();
130         }
131
132         bool canSetIndex(unsigned i) { return i < m_vectorLength; }
133         void setIndex(JSGlobalData& globalData, unsigned i, JSValue v)
134         {
135             ASSERT(canSetIndex(i));
136             
137             WriteBarrier<Unknown>& x = m_storage->m_vector[i];
138             if (!x) {
139                 ArrayStorage *storage = m_storage;
140                 ++storage->m_numValuesInVector;
141                 if (i >= storage->m_length)
142                     storage->m_length = i + 1;
143             }
144             x.set(globalData, this, v);
145         }
146         
147         void uncheckedSetIndex(JSGlobalData& globalData, unsigned i, JSValue v)
148         {
149             ASSERT(canSetIndex(i));
150             ArrayStorage *storage = m_storage;
151 #if CHECK_ARRAY_CONSISTENCY
152             ASSERT(storage->m_inCompactInitialization);
153 #endif
154             storage->m_vector[i].set(globalData, this, v);
155         }
156
157         void fillArgList(ExecState*, MarkedArgumentBuffer&);
158         void copyToRegisters(ExecState*, Register*, uint32_t);
159
160         static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype)
161         {
162             return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info);
163         }
164         
165         static ptrdiff_t storageOffset()
166         {
167             return OBJECT_OFFSETOF(JSArray, m_storage);
168         }
169
170         static ptrdiff_t vectorLengthOffset()
171         {
172             return OBJECT_OFFSETOF(JSArray, m_vectorLength);
173         }
174
175         static void visitChildren(JSCell*, SlotVisitor&);
176
177     protected:
178         static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesVisitChildren | OverridesGetPropertyNames | JSObject::StructureFlags;
179         static void put(JSCell*, ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
180
181         static bool deleteProperty(JSCell*, ExecState*, const Identifier& propertyName);
182         static bool deletePropertyByIndex(JSCell*, ExecState*, unsigned propertyName);
183         static void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
184
185         void* subclassData() const;
186         void setSubclassData(void*);
187
188     private:
189         bool getOwnPropertySlotSlowCase(ExecState*, unsigned propertyName, PropertySlot&);
190         void putSlowCase(ExecState*, unsigned propertyName, JSValue);
191
192         unsigned getNewVectorLength(unsigned desiredLength);
193         bool increaseVectorLength(unsigned newLength);
194         bool increaseVectorPrefixLength(unsigned newLength);
195         
196         unsigned compactForSorting();
197
198         enum ConsistencyCheckType { NormalConsistencyCheck, DestructorConsistencyCheck, SortConsistencyCheck };
199         void checkConsistency(ConsistencyCheckType = NormalConsistencyCheck);
200
201         unsigned m_vectorLength; // The valid length of m_vector
202         int m_indexBias; // The number of JSValue sized blocks before ArrayStorage.
203         ArrayStorage *m_storage;
204     };
205
206     JSArray* asArray(JSValue);
207
208     inline JSArray* asArray(JSCell* cell)
209     {
210         ASSERT(cell->inherits(&JSArray::s_info));
211         return static_cast<JSArray*>(cell);
212     }
213
214     inline JSArray* asArray(JSValue value)
215     {
216         return asArray(value.asCell());
217     }
218
219     inline bool isJSArray(JSGlobalData* globalData, JSCell* cell) { return cell->vptr() == globalData->jsArrayVPtr; }
220     inline bool isJSArray(JSGlobalData* globalData, JSValue v) { return v.isCell() && isJSArray(globalData, v.asCell()); }
221
222     // Rule from ECMA 15.2 about what an array index is.
223     // Must exactly match string form of an unsigned integer, and be less than 2^32 - 1.
224     inline unsigned Identifier::toArrayIndex(bool& ok) const
225     {
226         unsigned i = toUInt32(ok);
227         if (ok && i >= 0xFFFFFFFFU)
228             ok = false;
229         return i;
230     }
231
232 } // namespace JSC
233
234 #endif // JSArray_h