JavaScriptCore:

	- replaced List class with a vector rather than a linked list, changed it
	to use a pool of instances instead of all the nodes allocated off of the
	heap; gives 10% gain on iBench

        * kjs/list.h: Complete rewrite.
        * kjs/list.cpp: Ditto.

        * kjs/array_object.cpp: (compareWithCompareFunctionForQSort): Go back to
	doing a clear and two appends here. Fast with the new list implementation.

        * kjs/collector.h: Remove _COLLECTOR hack and just make rootObjectClasses
	return a const void *.
        * kjs/collector.cpp: Remove _COLLECTOR hack, and various other minor tweaks.

WebCore:

        * khtml/ecma/kjs_window.cpp: Remove _COLLECTOR hack.

        * kwq/WebCoreJavaScript.h:
        * kwq/WebCoreJavaScript.mm:
        (+[WebCoreJavaScript rootObjectClasses]):
	Update for name change -- root object classes, not all live object classes.

        * force-js-clean-timestamp: Make sure we don't have more build problems.

WebKit:

        * Misc.subproj/WebCoreStatistics.h:
        * Misc.subproj/WebCoreStatistics.m:
        (+[WebCoreStatistics javaScriptRootObjectClasses]):
	Update for name change -- root object classes, not all live object classes.

WebBrowser:

        * Debug/CacheController.m: (-[CacheController refreshJavaScriptStatisticsMatrix]):
	Update for name change -- root object classes, not all live object classes.


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@2843 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/JavaScriptCore/kjs/list.cpp b/JavaScriptCore/kjs/list.cpp
index 37c22f0..a06c6c2 100644
--- a/JavaScriptCore/kjs/list.cpp
+++ b/JavaScriptCore/kjs/list.cpp
@@ -1,8 +1,6 @@
-// -*- c-basic-offset: 2 -*-
 /*
  *  This file is part of the KDE libraries
- *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
- *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ *  Copyright (C) 2002 Apple Computer, Inc.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Library General Public
@@ -21,23 +19,38 @@
  *
  */
 
-#include "value.h"
-#include "object.h"
-#include "types.h"
-#include "interpreter.h"
-
-#include <assert.h>
-#include <math.h>
-#include <stdio.h>
+#include "list.h"
 
 #include "internal.h"
-#include "collector.h"
-#include "operations.h"
-#include "error_object.h"
-#include "nodes.h"
 
 #define DUMP_STATISTICS 0
 
+namespace KJS {
+
+// tunable parameters
+const int poolSize = 16; // must be a power of 2
+const int inlineValuesSize = 4;
+
+// derived constants
+const int poolSizeMask = poolSize - 1;
+
+enum ListImpState { unusedInPool = 0, usedInPool, usedOnHeap, immortal };
+
+struct ListImp : ListImpBase
+{
+    ListImpState state;
+    ValueImp *values[inlineValuesSize];
+    int capacity;
+    ValueImp **overflow;
+
+#if DUMP_STATISTICS
+    int sizeHighWaterMark;
+#endif
+};
+
+static ListImp pool[poolSize];
+static int poolCursor;
+
 #if DUMP_STATISTICS
 
 static int numLists;
@@ -48,9 +61,6 @@
 static int numListsDestroyed;
 static int numListsBiggerThan[17];
 
-static int numNodesAllocated;
-static int numNodesWouldNeedToBeCopied;
-
 struct ListStatisticsExitLogger { ~ListStatisticsExitLogger(); };
 
 static ListStatisticsExitLogger logger;
@@ -60,371 +70,171 @@
     printf("\nKJS::List statistics:\n\n");
     printf("%d lists were allocated\n", numLists);
     printf("%d lists was the high water mark\n", numListsHighWaterMark);
-    printf("largest list had %d elements\n\n", listSizeHighWaterMark);
-    printf("%d nodes were allocated\n", numNodesAllocated);
-    printf("%d node copies would have been necessary if lists didn't share\n\n", numNodesWouldNeedToBeCopied);
-    for (int i = 0; i < 17; i++) {
-        printf("%.1f%% of the lists (%d) had more than %d element%s\n",
-            100.0 * numListsBiggerThan[i] / numListsDestroyed,
-            numListsBiggerThan[i],
-            i, i == 1 ? "" : "s");
+    printf("largest list had %d elements\n", listSizeHighWaterMark);
+    if (numListsDestroyed) {
+        putc('\n', stdout);
+        for (int i = 0; i < 17; i++) {
+            printf("%.1f%% of the lists (%d) had more than %d element%s\n",
+                100.0 * numListsBiggerThan[i] / numListsDestroyed,
+                numListsBiggerThan[i],
+                i, i == 1 ? "" : "s");
+        }
+        putc('\n', stdout);
     }
 }
 
 #endif
 
-namespace KJS {
-
-  struct ListNode {
-    ListNode(const Value &val, ListNode *p, ListNode *n)
-      : member(val.imp()), prev(p), next(n) { }
-    ListNode(ValueImp *val, ListNode *p, ListNode *n)
-      : member(val), prev(p), next(n) { }
-    ValueImp *member;
-    ListNode *prev, *next;
-  };
-
-  struct ListHookNode : public ListNode {
-    ListHookNode() : ListNode(0, this, this), listRefCount(1), nodesRefCount(1)
-#if DUMP_STATISTICS
-        , sizeHighWaterMark(0)
-#endif
-        { }
+static inline ListImp *allocateListImp()
+{
+    // Find a free one in the pool.
+    int c = poolCursor;
+    int i = c;
+    do {
+        ListImp *imp = &pool[i];
+        ListImpState s = imp->state;
+        i = (i + 1) & poolSizeMask;
+        if (s == unusedInPool) {
+            poolCursor = i;
+            imp->state = usedInPool;
+            return imp;
+        }
+    } while (i != c);
     
-    int listRefCount;
-    int nodesRefCount;
+    ListImp *imp = new ListImp;
+    imp->state = usedOnHeap;
+    return imp;
+}
+
+static inline void deallocateListImp(ListImp *imp)
+{
+    if (imp->state == usedInPool)
+        imp->state = unusedInPool;
+    else
+        delete imp;
+}
+
+List::List() : _impBase(allocateListImp())
+{
+    ListImp *imp = static_cast<ListImp *>(_impBase);
+    imp->size = 0;
+    imp->refCount = 1;
+    imp->capacity = 0;
+    imp->overflow = 0;
 
 #if DUMP_STATISTICS
-    int sizeHighWaterMark;
-#endif
-  };
-
-// ------------------------------ ListIterator ---------------------------------
-
-ValueImp* ListIterator::operator->() const
-{
-  return node->member;
-}
-
-Value ListIterator::operator*() const
-{
-  return Value(node->member);
-}
-
-Value ListIterator::operator++()
-{
-  node = node->next;
-  return Value(node->member);
-}
-
-Value ListIterator::operator++(int)
-{
-  const ListNode *n = node;
-  ++*this;
-  return Value(n->member);
-}
-
-Value ListIterator::operator--()
-{
-  node = node->prev;
-  return Value(node->member);
-}
-
-Value ListIterator::operator--(int)
-{
-  const ListNode *n = node;
-  --*this;
-  return Value(n->member);
-}
-
-// ------------------------------ List -----------------------------------------
-
-List::List() : hook(new ListHookNode)
-{
-#if DUMP_STATISTICS
-  if (++numLists > numListsHighWaterMark)
-    numListsHighWaterMark = numLists;
+    if (++numLists > numListsHighWaterMark)
+        numListsHighWaterMark = numLists;
+    imp->sizeHighWaterMark = 0;
 #endif
 }
 
-List::List(const List& l) : hook(l.hook)
+inline void List::derefValues()
 {
-#if DUMP_STATISTICS
-  if (++numLists > numListsHighWaterMark)
-    numListsHighWaterMark = numLists;
-  numNodesWouldNeedToBeCopied += size();
-#endif
-
-  ++hook->listRefCount;
-  if (hook->nodesRefCount++ == 0)
-    refAll();
+    ListImp *imp = static_cast<ListImp *>(_impBase);
+    
+    int size = imp->size;
+    
+    int inlineSize = MIN(size, inlineValuesSize);
+    for (int i = 0; i != inlineSize; ++i)
+        imp->values[i]->deref();
+    
+    int overflowSize = size - inlineSize;
+    ValueImp **overflow = imp->overflow;
+    for (int i = 0; i != overflowSize; ++i)
+        overflow[i]->deref();
 }
 
-List& List::operator=(const List& l)
+void List::release()
 {
-  List(l).swap(*this);
-  return *this;
-}
-
-List::~List()
-{
+    ListImp *imp = static_cast<ListImp *>(_impBase);
+    
 #if DUMP_STATISTICS
-  --numLists;
-#endif
-
-  if (--hook->nodesRefCount == 0)
-    derefAll();
-  
-  if (--hook->listRefCount == 0) {
-#if DUMP_STATISTICS
+    --numLists;
     ++numListsDestroyed;
     for (int i = 0; i < 17; i++)
-      if (hook->sizeHighWaterMark > i)
-        ++numListsBiggerThan[i];
+        if (imp->sizeHighWaterMark > i)
+            ++numListsBiggerThan[i];
 #endif
 
-    assert(hook->nodesRefCount == 0);
-    clearInternal();
-    delete hook;
-  }
+    derefValues();
+    delete [] imp->overflow;
+    deallocateListImp(imp);
 }
 
-void List::append(const Value& val)
+ValueImp *List::impAt(int i) const
 {
-  ListNode *n = new ListNode(val, hook->prev, hook);
-  if (hook->nodesRefCount)
-    n->member->ref();
-  hook->prev->next = n;
-  hook->prev = n;
-
-#if DUMP_STATISTICS
-  ++numNodesAllocated;
-  int s = size();
-  if (s > hook->sizeHighWaterMark) {
-    hook->sizeHighWaterMark = s;
-    if (s > listSizeHighWaterMark)
-     listSizeHighWaterMark = s;
-  }
-#endif
+    ListImp *imp = static_cast<ListImp *>(_impBase);
+    if ((unsigned)i >= (unsigned)imp->size)
+        return UndefinedImp::staticUndefined;
+    if (i < inlineValuesSize)
+        return imp->values[i];
+    return imp->overflow[i - inlineValuesSize];
 }
 
-void List::append(ValueImp *val)
-{
-  ListNode *n = new ListNode(val, hook->prev, hook);
-  if (hook->nodesRefCount)
-    val->ref();
-  hook->prev->next = n;
-  hook->prev = n;
-
-#if DUMP_STATISTICS
-  ++numNodesAllocated;
-  int s = size();
-  if (s > hook->sizeHighWaterMark) {
-    hook->sizeHighWaterMark = s;
-    if (s > listSizeHighWaterMark)
-     listSizeHighWaterMark = s;
-  }
-#endif
-}
-
-#if 0
-
-void List::prepend(const Value& val)
-{
-  ListNode *n = new ListNode(val, hook, hook->next);
-  if (hook->nodesRefCount)
-    n->member->ref();
-  hook->next->prev = n;
-  hook->next = n;
-
-#if DUMP_STATISTICS
-  ++numNodesAllocated;
-  int s = size();
-  if (s > hook->sizeHighWaterMark) {
-    hook->sizeHighWaterMark = s;
-    if (s > listSizeHighWaterMark)
-     listSizeHighWaterMark = s;
-  }
-#endif
-}
-
-#endif
-
-void List::prepend(ValueImp *val)
-{
-  ListNode *n = new ListNode(val, hook, hook->next);
-  if (hook->nodesRefCount)
-    val->ref();
-  hook->next->prev = n;
-  hook->next = n;
-
-#if DUMP_STATISTICS
-  ++numNodesAllocated;
-  int s = size();
-  if (s > hook->sizeHighWaterMark) {
-    hook->sizeHighWaterMark = s;
-    if (s > listSizeHighWaterMark)
-     listSizeHighWaterMark = s;
-  }
-#endif
-}
-
-void List::prependList(const List& lst)
-{
-  ListNode *otherHook = lst.hook;
-  ListNode *n = otherHook->prev;
-  while (n != otherHook) {
-    prepend(n->member);
-    n = n->prev;
-  }
-}
-
-void List::removeFirst()
-{
-  erase(hook->next);
-}
-
-#if 0
-
-void List::removeLast()
-{
-  erase(hook->prev);
-}
-
-void List::remove(const Value &val)
-{
-  if (val.isNull())
-    return;
-  for (ListNode *n = hook->next; n != hook; n = n->next)
-    if (n->member == val.imp()) {
-      erase(n);
-      return;
-    }
-}
-
-#endif
-
 void List::clear()
 {
-  if (hook->nodesRefCount)
-    derefAll();
-  clearInternal();
+    derefValues();
+    _impBase->size = 0;
 }
 
-void List::clearInternal()
+void List::append(ValueImp *v)
 {
-  ListNode *n = hook->next;
-  while (n != hook) {
-    n = n->next;
-    delete n->prev;
-  }
+    ListImp *imp = static_cast<ListImp *>(_impBase);
 
-  hook->next = hook;
-  hook->prev = hook;
+    int i = imp->size++;
+
+#if DUMP_STATISTICS
+    if (imp->size > listSizeHighWaterMark)
+        listSizeHighWaterMark = imp->size;
+#endif
+
+    v->ref();
+    
+    if (i < inlineValuesSize) {
+        imp->values[i] = v;
+        return;
+    }
+    
+    if (i >= imp->capacity) {
+        int newCapacity = i * 2;
+        ValueImp **newOverflow = new ValueImp * [newCapacity - inlineValuesSize];
+        ValueImp **oldOverflow = imp->overflow;
+        int oldOverflowSize = i - inlineValuesSize;
+        for (int j = 0; j != oldOverflowSize; j++)
+            newOverflow[j] = oldOverflow[j];
+        delete [] oldOverflow;
+        imp->overflow = newOverflow;
+        imp->capacity = newCapacity;
+    }
+    
+    imp->overflow[i - inlineValuesSize] = v;
 }
 
-List List::copy() const
+List List::copyTail() const
 {
-  List newList;
-  newList.prependList(*this);
-  return newList;
-}
+    List copy;
 
-ListIterator List::begin() const
-{
-  return ListIterator(hook->next);
-}
+    ListImp *imp = static_cast<ListImp *>(_impBase);
 
-ListIterator List::end() const
-{
-  return ListIterator(hook);
-}
+    int size = imp->size;
 
-bool List::isEmpty() const
-{
-  return hook->prev == hook;
-}
+    int inlineSize = MIN(size, inlineValuesSize);
+    for (int i = 0; i != inlineSize; ++i)
+        copy.append(imp->values[i]);
 
-int List::size() const
-{
-  int s = 0;
-  for (ListNode *n = hook->next; n != hook; n = n->next)
-    s++;
-  return s;
-}
+    ValueImp **overflow = imp->overflow;
+    int overflowSize = size - inlineSize;
+    for (int i = 0; i != overflowSize; ++i)
+        copy.append(overflow[i]);
 
-Value List::at(int i) const
-{
-  if (i < 0 || i >= size())
-    return Undefined();
-
-  ListIterator it = begin();
-  int j = 0;
-  while ((j++ < i))
-    it++;
-
-  return *it;
-}
-
-Value List::operator[](int i) const
-{
-  return at(i);
+    return copy;
 }
 
 const List &List::empty()
 {
-  static List l;
-  return l;
-}
-
-void List::erase(ListNode *n)
-{
-  if (n != hook) {
-    if (hook->nodesRefCount)
-      n->member->deref();
-    n->next->prev = n->prev;
-    n->prev->next = n->next;
-    delete n;
-  }
-}
-
-void List::refAll()
-{
-  for (ListNode *n = hook->next; n != hook; n = n->next)
-    n->member->ref();
-}
-
-void List::derefAll()
-{
-  for (ListNode *n = hook->next; n != hook; n = n->next)
-    n->member->deref();
-}
-
-void List::swap(List &other)
-{
-  ListHookNode *tmp = hook;
-  hook = other.hook;
-  other.hook = tmp;
-}
-
-void List::replaceFirst(ValueImp *v)
-{
-  ListNode *n = hook->next;
-  if (hook->nodesRefCount) {
-    v->ref();
-    n->member->deref();
-  }
-  n->member = v;
-}
-
-void List::replaceLast(ValueImp *v)
-{
-  ListNode *n = hook->prev;
-  if (hook->nodesRefCount) {
-    v->ref();
-    n->member->deref();
-  }
-  n->member = v;
+    static List emptyList;
+    return emptyList;
 }
 
 } // namespace KJS