27 #define MIN(a,b) ((a) < (b) ? (a) : (b))
30 #define DUMP_STATISTICS 0
35 const int poolSize = 32;
36 const int inlineValuesSize = 4;
39 const int poolSizeMask = poolSize - 1;
41 enum ListImpState { unusedInPool = 0, usedInPool, usedOnHeap, immortal };
43 struct ListImp : ListImpBase
46 ValueImp *values[inlineValuesSize];
51 int sizeHighWaterMark;
55 static ListImp pool[poolSize];
56 static int poolCursor;
61 static int numListsHighWaterMark;
63 static int listSizeHighWaterMark;
65 static int numListsDestroyed;
66 static int numListsBiggerThan[17];
68 struct ListStatisticsExitLogger { ~ListStatisticsExitLogger(); };
70 static ListStatisticsExitLogger logger;
72 ListStatisticsExitLogger::~ListStatisticsExitLogger()
74 printf(
"\nKJS::List statistics:\n\n");
75 printf(
"%d lists were allocated\n", numLists);
76 printf(
"%d lists was the high water mark\n", numListsHighWaterMark);
77 printf(
"largest list had %d elements\n", listSizeHighWaterMark);
78 if (numListsDestroyed) {
80 for (
int i = 0; i < 17; i++) {
81 printf(
"%.1f%% of the lists (%d) had more than %d element%s\n",
82 100.0 * numListsBiggerThan[i] / numListsDestroyed,
83 numListsBiggerThan[i],
84 i, i == 1 ?
"" :
"s");
92 static inline ListImp *allocateListImp()
98 ListImp *imp = &pool[i];
99 ListImpState s = imp->state;
100 i = (i + 1) & poolSizeMask;
101 if (s == unusedInPool) {
103 imp->state = usedInPool;
108 ListImp *imp =
new ListImp;
109 imp->state = usedOnHeap;
113 static inline void deallocateListImp(ListImp *imp)
115 if (imp->state == usedInPool)
116 imp->state = unusedInPool;
121 List::List() : _impBase(allocateListImp()), _needsMarking(false)
123 ListImp *imp =
static_cast<ListImp *
>(_impBase);
129 if (!_needsMarking) {
130 imp->valueRefCount = 1;
133 if (++numLists > numListsHighWaterMark)
134 numListsHighWaterMark = numLists;
135 imp->sizeHighWaterMark = 0;
139 List::List(
bool needsMarking) : _impBase(allocateListImp()), _needsMarking(needsMarking)
141 ListImp *imp =
static_cast<ListImp *
>(_impBase);
147 if (!_needsMarking) {
148 imp->valueRefCount = 1;
152 if (++numLists > numListsHighWaterMark)
153 numListsHighWaterMark = numLists;
154 imp->sizeHighWaterMark = 0;
158 void List::derefValues()
160 ListImp *imp =
static_cast<ListImp *
>(_impBase);
162 int size = imp->size;
164 int inlineSize = MIN(size, inlineValuesSize);
165 for (
int i = 0; i != inlineSize; ++i)
166 imp->values[i]->deref();
168 int overflowSize = size - inlineSize;
169 ValueImp **overflow = imp->overflow;
170 for (
int i = 0; i != overflowSize; ++i)
171 overflow[i]->deref();
174 void List::refValues()
176 ListImp *imp =
static_cast<ListImp *
>(_impBase);
178 int size = imp->size;
180 int inlineSize = MIN(size, inlineValuesSize);
181 for (
int i = 0; i != inlineSize; ++i)
182 imp->values[i]->ref();
184 int overflowSize = size - inlineSize;
185 ValueImp **overflow = imp->overflow;
186 for (
int i = 0; i != overflowSize; ++i)
190 void List::markValues()
192 ListImp *imp =
static_cast<ListImp *
>(_impBase);
194 int size = imp->size;
196 int inlineSize = MIN(size, inlineValuesSize);
197 for (
int i = 0; i != inlineSize; ++i) {
198 if (!imp->values[i]->marked()) {
199 imp->values[i]->mark();
203 int overflowSize = size - inlineSize;
204 ValueImp **overflow = imp->overflow;
205 for (
int i = 0; i != overflowSize; ++i) {
206 if (!overflow[i]->marked()) {
214 ListImp *imp =
static_cast<ListImp *
>(_impBase);
219 for (
int i = 0; i < 17; i++)
220 if (imp->sizeHighWaterMark > i)
221 ++numListsBiggerThan[i];
224 delete [] imp->overflow;
225 deallocateListImp(imp);
228 ValueImp *List::impAt(
int i)
const
230 ListImp *imp =
static_cast<ListImp *
>(_impBase);
231 if ((
unsigned)i >= (unsigned)imp->size)
232 return UndefinedImp::staticUndefined;
233 if (i < inlineValuesSize)
234 return imp->values[i];
235 return imp->overflow[i - inlineValuesSize];
240 if (_impBase->valueRefCount > 0) {
248 ListImp *imp =
static_cast<ListImp *
>(_impBase);
253 if (imp->size > listSizeHighWaterMark)
254 listSizeHighWaterMark = imp->size;
257 if (imp->valueRefCount > 0) {
261 if (i < inlineValuesSize) {
266 if (i >= imp->capacity) {
267 int newCapacity = i * 2;
268 ValueImp **newOverflow =
new ValueImp * [newCapacity - inlineValuesSize];
269 ValueImp **oldOverflow = imp->overflow;
270 int oldOverflowSize = i - inlineValuesSize;
271 for (
int j = 0; j != oldOverflowSize; j++)
272 newOverflow[j] = oldOverflow[j];
273 delete [] oldOverflow;
274 imp->overflow = newOverflow;
275 imp->capacity = newCapacity;
278 imp->overflow[i - inlineValuesSize] = v;
285 ListImp *imp =
static_cast<ListImp *
>(_impBase);
287 int size = imp->size;
289 int inlineSize = MIN(size, inlineValuesSize);
290 for (
int i = 0; i != inlineSize; ++i)
291 copy.
append(imp->values[i]);
293 ValueImp **overflow = imp->overflow;
294 int overflowSize = size - inlineSize;
295 for (
int i = 0; i != overflowSize; ++i)
306 ListImp *imp =
static_cast<ListImp *
>(_impBase);
308 int size = imp->size;
310 int inlineSize = MIN(size, inlineValuesSize);
311 for (
int i = 1; i < inlineSize; ++i)
312 copy.
append(imp->values[i]);
314 ValueImp **overflow = imp->overflow;
315 int overflowSize = size - inlineSize;
316 for (
int i = 0; i < overflowSize; ++i)
324 static List emptyList;
ValueImp is the base type for all primitives (Undefined, Null, Boolean, String, Number) and objects i...
bool append(const KKeySequence &keySeq)