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.
38 class JSArray
: public JSObject
{
43 explicit JSArray(NonNullPassRefPtr
<Structure
>);
44 JSArray(NonNullPassRefPtr
<Structure
>, unsigned initialLength
);
45 JSArray(NonNullPassRefPtr
<Structure
>, const ArgList
& initialValues
);
48 virtual bool getOwnPropertySlot(ExecState
*, const Identifier
& propertyName
, PropertySlot
&);
49 virtual bool getOwnPropertySlot(ExecState
*, unsigned propertyName
, PropertySlot
&);
50 virtual bool getOwnPropertyDescriptor(ExecState
*, const Identifier
&, PropertyDescriptor
&);
51 virtual void put(ExecState
*, unsigned propertyName
, JSValue
); // FIXME: Make protected and add setItem.
53 static JS_EXPORTDATA
const ClassInfo info
;
55 unsigned length() const { return m_storage
->m_length
; }
56 void setLength(unsigned); // OK to use on new arrays, but not if it might be a RegExpMatchArray.
58 void sort(ExecState
*);
59 void sort(ExecState
*, JSValue compareFunction
, CallType
, const CallData
&);
60 void sortNumeric(ExecState
*, JSValue compareFunction
, CallType
, const CallData
&);
62 void push(ExecState
*, JSValue
);
65 bool canGetIndex(unsigned i
) { return i
< m_vectorLength
&& m_storage
->m_vector
[i
]; }
66 JSValue
getIndex(unsigned i
)
68 ASSERT(canGetIndex(i
));
69 return m_storage
->m_vector
[i
];
72 bool canSetIndex(unsigned i
) { return i
< m_vectorLength
; }
73 void setIndex(unsigned i
, JSValue v
)
75 ASSERT(canSetIndex(i
));
76 JSValue
& x
= m_storage
->m_vector
[i
];
78 ++m_storage
->m_numValuesInVector
;
79 if (i
>= m_storage
->m_length
)
80 m_storage
->m_length
= i
+ 1;
85 void fillArgList(ExecState
*, MarkedArgumentBuffer
&);
86 void copyToRegisters(ExecState
*, Register
*, uint32_t);
88 static PassRefPtr
<Structure
> createStructure(JSValue prototype
)
90 return Structure::create(prototype
, TypeInfo(ObjectType
, StructureFlags
));
93 inline void markChildrenDirect(MarkStack
& markStack
);
96 static const unsigned StructureFlags
= OverridesGetOwnPropertySlot
| OverridesMarkChildren
| OverridesGetPropertyNames
| JSObject::StructureFlags
;
97 virtual void put(ExecState
*, const Identifier
& propertyName
, JSValue
, PutPropertySlot
&);
98 virtual bool deleteProperty(ExecState
*, const Identifier
& propertyName
);
99 virtual bool deleteProperty(ExecState
*, unsigned propertyName
);
100 virtual void getOwnPropertyNames(ExecState
*, PropertyNameArray
&);
101 virtual void markChildren(MarkStack
&);
103 void* lazyCreationData();
104 void setLazyCreationData(void*);
107 virtual const ClassInfo
* classInfo() const { return &info
; }
109 bool getOwnPropertySlotSlowCase(ExecState
*, unsigned propertyName
, PropertySlot
&);
110 void putSlowCase(ExecState
*, unsigned propertyName
, JSValue
);
112 bool increaseVectorLength(unsigned newLength
);
114 unsigned compactForSorting();
116 enum ConsistencyCheckType
{ NormalConsistencyCheck
, DestructorConsistencyCheck
, SortConsistencyCheck
};
117 void checkConsistency(ConsistencyCheckType
= NormalConsistencyCheck
);
119 unsigned m_vectorLength
;
120 ArrayStorage
* m_storage
;
123 JSArray
* asArray(JSValue
);
125 inline JSArray
* asArray(JSCell
* cell
)
127 ASSERT(cell
->inherits(&JSArray::info
));
128 return static_cast<JSArray
*>(cell
);
131 inline JSArray
* asArray(JSValue value
)
133 return asArray(value
.asCell());
136 inline bool isJSArray(JSGlobalData
* globalData
, JSValue v
)
138 return v
.isCell() && v
.asCell()->vptr() == globalData
->jsArrayVPtr
;
140 inline bool isJSArray(JSGlobalData
* globalData
, JSCell
* cell
) { return cell
->vptr() == globalData
->jsArrayVPtr
; }
142 inline void JSArray::markChildrenDirect(MarkStack
& markStack
)
144 JSObject::markChildrenDirect(markStack
);
146 ArrayStorage
* storage
= m_storage
;
148 unsigned usedVectorLength
= std::min(storage
->m_length
, m_vectorLength
);
149 markStack
.appendValues(storage
->m_vector
, usedVectorLength
, MayContainNullValues
);
151 if (SparseArrayValueMap
* map
= storage
->m_sparseValueMap
) {
152 SparseArrayValueMap::iterator end
= map
->end();
153 for (SparseArrayValueMap::iterator it
= map
->begin(); it
!= end
; ++it
)
154 markStack
.append(it
->second
);
158 inline void MarkStack::markChildren(JSCell
* cell
)
160 ASSERT(Heap::isCellMarked(cell
));
161 if (!cell
->structure()->typeInfo().overridesMarkChildren()) {
163 asObject(cell
)->markChildrenDirect(*this);
165 ASSERT(!m_isCheckingForDefaultMarkViolation
);
166 m_isCheckingForDefaultMarkViolation
= true;
167 cell
->markChildren(*this);
168 ASSERT(m_isCheckingForDefaultMarkViolation
);
169 m_isCheckingForDefaultMarkViolation
= false;
173 if (cell
->vptr() == m_jsArrayVPtr
) {
174 asArray(cell
)->markChildrenDirect(*this);
177 cell
->markChildren(*this);
180 inline void MarkStack::drain()
182 while (!m_markSets
.isEmpty() || !m_values
.isEmpty()) {
183 while (!m_markSets
.isEmpty() && m_values
.size() < 50) {
184 ASSERT(!m_markSets
.isEmpty());
185 MarkSet
& current
= m_markSets
.last();
186 ASSERT(current
.m_values
);
187 JSValue
* end
= current
.m_end
;
188 ASSERT(current
.m_values
);
189 ASSERT(current
.m_values
!= end
);
190 findNextUnmarkedNullValue
:
191 ASSERT(current
.m_values
!= end
);
192 JSValue value
= *current
.m_values
;
196 if (!value
|| !value
.isCell() || Heap::isCellMarked(cell
= value
.asCell())) {
197 if (current
.m_values
== end
) {
198 m_markSets
.removeLast();
201 goto findNextUnmarkedNullValue
;
204 Heap::markCell(cell
);
205 if (cell
->structure()->typeInfo().type() < CompoundType
) {
206 if (current
.m_values
== end
) {
207 m_markSets
.removeLast();
210 goto findNextUnmarkedNullValue
;
213 if (current
.m_values
== end
)
214 m_markSets
.removeLast();
218 while (!m_values
.isEmpty())
219 markChildren(m_values
.removeLast());