2 * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
3 * Copyright (C) 2003, 2007, 2008, 2009 Apple Inc. All rights reserved.
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.
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.
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
28 typedef HashMap
<unsigned, JSValue
> SparseArrayValueMap
;
32 unsigned m_numValuesInVector
;
33 SparseArrayValueMap
* m_sparseValueMap
;
34 void* lazyCreationData
; // A JSArray subclass can use this to fill the vector lazily.
35 size_t reportedMapCapacity
;
39 class JSArray
: public JSObject
{
44 explicit JSArray(NonNullPassRefPtr
<Structure
>);
45 JSArray(NonNullPassRefPtr
<Structure
>, unsigned initialLength
);
46 JSArray(NonNullPassRefPtr
<Structure
>, const ArgList
& initialValues
);
49 virtual bool getOwnPropertySlot(ExecState
*, const Identifier
& propertyName
, PropertySlot
&);
50 virtual bool getOwnPropertySlot(ExecState
*, unsigned propertyName
, PropertySlot
&);
51 virtual bool getOwnPropertyDescriptor(ExecState
*, const Identifier
&, PropertyDescriptor
&);
52 virtual void put(ExecState
*, unsigned propertyName
, JSValue
); // FIXME: Make protected and add setItem.
54 static JS_EXPORTDATA
const ClassInfo info
;
56 unsigned length() const { return m_storage
->m_length
; }
57 void setLength(unsigned); // OK to use on new arrays, but not if it might be a RegExpMatchArray.
59 void sort(ExecState
*);
60 void sort(ExecState
*, JSValue compareFunction
, CallType
, const CallData
&);
61 void sortNumeric(ExecState
*, JSValue compareFunction
, CallType
, const CallData
&);
63 void push(ExecState
*, JSValue
);
66 bool canGetIndex(unsigned i
) { return i
< m_vectorLength
&& m_storage
->m_vector
[i
]; }
67 JSValue
getIndex(unsigned i
)
69 ASSERT(canGetIndex(i
));
70 return m_storage
->m_vector
[i
];
73 bool canSetIndex(unsigned i
) { return i
< m_vectorLength
; }
74 void setIndex(unsigned i
, JSValue v
)
76 ASSERT(canSetIndex(i
));
77 JSValue
& x
= m_storage
->m_vector
[i
];
79 ++m_storage
->m_numValuesInVector
;
80 if (i
>= m_storage
->m_length
)
81 m_storage
->m_length
= i
+ 1;
86 void fillArgList(ExecState
*, MarkedArgumentBuffer
&);
87 void copyToRegisters(ExecState
*, Register
*, uint32_t);
89 static PassRefPtr
<Structure
> createStructure(JSValue prototype
)
91 return Structure::create(prototype
, TypeInfo(ObjectType
, StructureFlags
), AnonymousSlotCount
);
94 inline void markChildrenDirect(MarkStack
& markStack
);
97 static const unsigned StructureFlags
= OverridesGetOwnPropertySlot
| OverridesMarkChildren
| OverridesGetPropertyNames
| JSObject::StructureFlags
;
98 virtual void put(ExecState
*, const Identifier
& propertyName
, JSValue
, PutPropertySlot
&);
99 virtual bool deleteProperty(ExecState
*, const Identifier
& propertyName
);
100 virtual bool deleteProperty(ExecState
*, unsigned propertyName
);
101 virtual void getOwnPropertyNames(ExecState
*, PropertyNameArray
&, EnumerationMode mode
= ExcludeDontEnumProperties
);
102 virtual void markChildren(MarkStack
&);
104 void* lazyCreationData();
105 void setLazyCreationData(void*);
108 virtual const ClassInfo
* classInfo() const { return &info
; }
110 bool getOwnPropertySlotSlowCase(ExecState
*, unsigned propertyName
, PropertySlot
&);
111 void putSlowCase(ExecState
*, unsigned propertyName
, JSValue
);
113 bool increaseVectorLength(unsigned newLength
);
115 unsigned compactForSorting();
117 enum ConsistencyCheckType
{ NormalConsistencyCheck
, DestructorConsistencyCheck
, SortConsistencyCheck
};
118 void checkConsistency(ConsistencyCheckType
= NormalConsistencyCheck
);
120 unsigned m_vectorLength
;
121 ArrayStorage
* m_storage
;
124 JSArray
* asArray(JSValue
);
126 inline JSArray
* asArray(JSCell
* cell
)
128 ASSERT(cell
->inherits(&JSArray::info
));
129 return static_cast<JSArray
*>(cell
);
132 inline JSArray
* asArray(JSValue value
)
134 return asArray(value
.asCell());
137 inline bool isJSArray(JSGlobalData
* globalData
, JSValue v
)
139 return v
.isCell() && v
.asCell()->vptr() == globalData
->jsArrayVPtr
;
141 inline bool isJSArray(JSGlobalData
* globalData
, JSCell
* cell
) { return cell
->vptr() == globalData
->jsArrayVPtr
; }
143 inline void JSArray::markChildrenDirect(MarkStack
& markStack
)
145 JSObject::markChildrenDirect(markStack
);
147 ArrayStorage
* storage
= m_storage
;
149 unsigned usedVectorLength
= std::min(storage
->m_length
, m_vectorLength
);
150 markStack
.appendValues(storage
->m_vector
, usedVectorLength
, MayContainNullValues
);
152 if (SparseArrayValueMap
* map
= storage
->m_sparseValueMap
) {
153 SparseArrayValueMap::iterator end
= map
->end();
154 for (SparseArrayValueMap::iterator it
= map
->begin(); it
!= end
; ++it
)
155 markStack
.append(it
->second
);
159 inline void MarkStack::markChildren(JSCell
* cell
)
161 ASSERT(Heap::isCellMarked(cell
));
162 if (!cell
->structure()->typeInfo().overridesMarkChildren()) {
164 asObject(cell
)->markChildrenDirect(*this);
166 ASSERT(!m_isCheckingForDefaultMarkViolation
);
167 m_isCheckingForDefaultMarkViolation
= true;
168 cell
->markChildren(*this);
169 ASSERT(m_isCheckingForDefaultMarkViolation
);
170 m_isCheckingForDefaultMarkViolation
= false;
174 if (cell
->vptr() == m_jsArrayVPtr
) {
175 asArray(cell
)->markChildrenDirect(*this);
178 cell
->markChildren(*this);
181 inline void MarkStack::drain()
183 while (!m_markSets
.isEmpty() || !m_values
.isEmpty()) {
184 while (!m_markSets
.isEmpty() && m_values
.size() < 50) {
185 ASSERT(!m_markSets
.isEmpty());
186 MarkSet
& current
= m_markSets
.last();
187 ASSERT(current
.m_values
);
188 JSValue
* end
= current
.m_end
;
189 ASSERT(current
.m_values
);
190 ASSERT(current
.m_values
!= end
);
191 findNextUnmarkedNullValue
:
192 ASSERT(current
.m_values
!= end
);
193 JSValue value
= *current
.m_values
;
197 if (!value
|| !value
.isCell() || Heap::isCellMarked(cell
= value
.asCell())) {
198 if (current
.m_values
== end
) {
199 m_markSets
.removeLast();
202 goto findNextUnmarkedNullValue
;
205 Heap::markCell(cell
);
206 if (cell
->structure()->typeInfo().type() < CompoundType
) {
207 if (current
.m_values
== end
) {
208 m_markSets
.removeLast();
211 goto findNextUnmarkedNullValue
;
214 if (current
.m_values
== end
)
215 m_markSets
.removeLast();
219 while (!m_values
.isEmpty())
220 markChildren(m_values
.removeLast());