2
* Copyright (C) 2003, 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
4
* This library is free software; you can redistribute it and/or
5
* modify it under the terms of the GNU Library General Public
6
* License as published by the Free Software Foundation; either
7
* version 2 of the License, or (at your option) any later version.
9
* This library is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
* Library General Public License for more details.
14
* You should have received a copy of the GNU Library General Public License
15
* along with this library; see the file COPYING.LIB. If not, write to
16
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17
* Boston, MA 02110-1301, USA.
27
#define DUMP_STATISTICS 0
34
const int poolSize = 512;
35
const int inlineValuesSize = 5;
37
enum ListImpState { unusedInPool = 0, usedInPool, usedOnHeap, immortal };
39
struct ListImp : ListImpBase
46
JSValue *values[inlineValuesSize];
47
ListImp *nextInFreeList;
51
int sizeHighWaterMark;
57
struct HeapListImp : ListImp
59
HeapListImp *nextInHeapList;
60
HeapListImp *prevInHeapList;
63
static ListImp pool[poolSize];
64
static ListImp *poolFreeList;
65
static HeapListImp *heapList;
71
static int numListsHighWaterMark;
73
static int listSizeHighWaterMark;
75
static int numListsDestroyed;
76
static int numListsBiggerThan[17];
78
struct ListStatisticsExitLogger { ~ListStatisticsExitLogger(); };
80
static ListStatisticsExitLogger logger;
82
ListStatisticsExitLogger::~ListStatisticsExitLogger()
84
printf("\nKJS::List statistics:\n\n");
85
printf("%d lists were allocated\n", numLists);
86
printf("%d lists was the high water mark\n", numListsHighWaterMark);
87
printf("largest list had %d elements\n", listSizeHighWaterMark);
88
if (numListsDestroyed) {
90
for (int i = 0; i < 17; i++) {
91
printf("%.1f%% of the lists (%d) had more than %d element%s\n",
92
100.0 * numListsBiggerThan[i] / numListsDestroyed,
93
numListsBiggerThan[i],
94
i, i == 1 ? "" : "s");
102
inline void ListImp::markValues()
104
int inlineSize = min(size, inlineValuesSize);
105
for (int i = 0; i != inlineSize; ++i) {
106
if (!values[i]->marked()) {
111
int overflowSize = size - inlineSize;
112
for (int i = 0; i != overflowSize; ++i) {
113
if (!overflow[i]->marked()) {
119
void List::markProtectedLists()
124
for (int i = 0; i < poolSize && seen < used; i++) {
125
if (pool[i].state == usedInPool) {
127
if (pool[i].valueRefCount > 0) {
128
pool[i].markValues();
133
for (HeapListImp *l = heapList; l; l = l->nextInHeapList) {
134
if (l->valueRefCount > 0) {
141
static inline ListImp *allocateListImp()
143
ASSERT(JSLock::lockCount() > 0);
145
// Find a free one in the pool.
146
if (poolUsed < poolSize) {
147
ListImp *imp = poolFreeList ? poolFreeList : &pool[0];
148
poolFreeList = imp->nextInFreeList ? imp->nextInFreeList : imp + 1;
149
imp->state = usedInPool;
154
HeapListImp *imp = new HeapListImp;
155
imp->state = usedOnHeap;
156
// link into heap list
158
heapList->prevInHeapList = imp;
160
imp->nextInHeapList = heapList;
161
imp->prevInHeapList = NULL;
167
List::List() : _impBase(allocateListImp())
169
ListImp *imp = static_cast<ListImp *>(_impBase);
172
imp->valueRefCount = 1;
177
if (++numLists > numListsHighWaterMark)
178
numListsHighWaterMark = numLists;
179
imp->sizeHighWaterMark = 0;
183
void List::markValues()
185
static_cast<ListImp *>(_impBase)->markValues();
190
ASSERT(JSLock::lockCount() > 0);
192
ListImp *imp = static_cast<ListImp *>(_impBase);
197
for (int i = 0; i < 17; i++)
198
if (imp->sizeHighWaterMark > i)
199
++numListsBiggerThan[i];
202
delete [] imp->overflow;
205
if (imp->state == usedInPool) {
206
imp->state = unusedInPool;
207
imp->nextInFreeList = poolFreeList;
211
ASSERT(imp->state == usedOnHeap);
212
HeapListImp *list = static_cast<HeapListImp *>(imp);
214
// unlink from heap list
215
if (!list->prevInHeapList) {
216
heapList = list->nextInHeapList;
218
heapList->prevInHeapList = NULL;
221
list->prevInHeapList->nextInHeapList = list->nextInHeapList;
222
if (list->nextInHeapList) {
223
list->nextInHeapList->prevInHeapList = list->prevInHeapList;
231
JSValue *List::at(int i) const
233
ListImp *imp = static_cast<ListImp *>(_impBase);
234
if ((unsigned)i >= (unsigned)imp->size)
235
return jsUndefined();
236
if (i < inlineValuesSize)
237
return imp->values[i];
238
return imp->overflow[i - inlineValuesSize];
246
void List::append(JSValue *v)
248
ASSERT(JSLock::lockCount() > 0);
250
ListImp *imp = static_cast<ListImp *>(_impBase);
255
if (imp->size > listSizeHighWaterMark)
256
listSizeHighWaterMark = imp->size;
259
if (i < inlineValuesSize) {
264
if (i >= imp->capacity) {
265
int newCapacity = i * 2;
266
JSValue** newOverflow = new JSValue* [newCapacity - inlineValuesSize];
267
JSValue** oldOverflow = imp->overflow;
268
int oldOverflowSize = i - inlineValuesSize;
269
for (int j = 0; j != oldOverflowSize; j++)
270
newOverflow[j] = oldOverflow[j];
271
delete [] oldOverflow;
272
imp->overflow = newOverflow;
273
imp->capacity = newCapacity;
276
imp->overflow[i - inlineValuesSize] = v;
279
List List::copy() const
282
copy.copyFrom(*this);
286
void List::copyFrom(const List& other)
288
ListImp *imp = static_cast<ListImp *>(other._impBase);
290
int size = imp->size;
292
int inlineSize = min(size, inlineValuesSize);
293
for (int i = 0; i != inlineSize; ++i)
294
append(imp->values[i]);
296
JSValue** overflow = imp->overflow;
297
int overflowSize = size - inlineSize;
298
for (int i = 0; i != overflowSize; ++i)
303
List List::copyTail() const
307
ListImp *imp = static_cast<ListImp *>(_impBase);
309
int size = imp->size;
311
int inlineSize = min(size, inlineValuesSize);
312
for (int i = 1; i < inlineSize; ++i)
313
copy.append(imp->values[i]);
315
JSValue** overflow = imp->overflow;
316
int overflowSize = size - inlineSize;
317
for (int i = 0; i < overflowSize; ++i)
318
copy.append(overflow[i]);
323
const List& List::empty()
325
static List* staticEmptyList = new List;
326
return *staticEmptyList;
329
List &List::operator=(const List &b)
331
ListImpBase *bImpBase = b._impBase;
332
++bImpBase->refCount;
333
++bImpBase->valueRefCount;