Commit 6afbb079 authored by darin's avatar darin

- prepare to reimplement KJS::List; move to its own file, add statistics

        * kjs/function_object.cpp: (FunctionProtoFuncImp::call): Use new copyTail()
	function rather than copy() and removeFirst().

        * kjs/identifier.cpp: Add statistics, off by default.
        * kjs/property_map.cpp: Add statistics, off by default.

        * kjs/list.cpp: Added. Moved code here. To be rewritten.
        * kjs/list.h: Added. Moved interface here. To be rewritten.

        * kjs/types.cpp: Removed.
        * kjs/types.h: Now just an empty header that includes other headers.

        * JavaScriptCore.pbproj/project.pbxproj: Add new files, rearrange.


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@2834 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 07dd4f5a
2002-11-22 Darin Adler <darin@apple.com>
- prepare to reimplement KJS::List; move to its own file, add statistics
* kjs/function_object.cpp: (FunctionProtoFuncImp::call): Use new copyTail()
function rather than copy() and removeFirst().
* kjs/identifier.cpp: Add statistics, off by default.
* kjs/property_map.cpp: Add statistics, off by default.
* kjs/list.cpp: Added. Moved code here. To be rewritten.
* kjs/list.h: Added. Moved interface here. To be rewritten.
* kjs/types.cpp: Removed.
* kjs/types.h: Now just an empty header that includes other headers.
* JavaScriptCore.pbproj/project.pbxproj: Add new files, rearrange.
2002-11-22 Maciej Stachowiak <mjs@apple.com>
- reduce cell size to 56 bytes from 64, now that nearly all
......
2002-11-22 Darin Adler <darin@apple.com>
- prepare to reimplement KJS::List; move to its own file, add statistics
* kjs/function_object.cpp: (FunctionProtoFuncImp::call): Use new copyTail()
function rather than copy() and removeFirst().
* kjs/identifier.cpp: Add statistics, off by default.
* kjs/property_map.cpp: Add statistics, off by default.
* kjs/list.cpp: Added. Moved code here. To be rewritten.
* kjs/list.h: Added. Moved interface here. To be rewritten.
* kjs/types.cpp: Removed.
* kjs/types.h: Now just an empty header that includes other headers.
* JavaScriptCore.pbproj/project.pbxproj: Add new files, rearrange.
2002-11-22 Maciej Stachowiak <mjs@apple.com>
- reduce cell size to 56 bytes from 64, now that nearly all
......
2002-11-22 Darin Adler <darin@apple.com>
- prepare to reimplement KJS::List; move to its own file, add statistics
* kjs/function_object.cpp: (FunctionProtoFuncImp::call): Use new copyTail()
function rather than copy() and removeFirst().
* kjs/identifier.cpp: Add statistics, off by default.
* kjs/property_map.cpp: Add statistics, off by default.
* kjs/list.cpp: Added. Moved code here. To be rewritten.
* kjs/list.h: Added. Moved interface here. To be rewritten.
* kjs/types.cpp: Removed.
* kjs/types.h: Now just an empty header that includes other headers.
* JavaScriptCore.pbproj/project.pbxproj: Add new files, rearrange.
2002-11-22 Maciej Stachowiak <mjs@apple.com>
- reduce cell size to 56 bytes from 64, now that nearly all
......
......@@ -226,6 +226,7 @@
938772E6038BFE19008635CE,
9374D3A9038D9D74008635CE,
9373524F038DA8C2008635CE,
931C6CF1038EE8DE008635CE,
);
isa = PBXHeadersBuildPhase;
runOnlyForDeploymentPostprocessing = 0;
......@@ -263,7 +264,6 @@
F692A8B70255597D01FF60F7,
F692A8B90255597D01FF60F7,
F692A8BB0255597D01FF60F7,
F692A8BF0255597D01FF60F7,
F692A8C10255597D01FF60F7,
F692A8C30255597D01FF60F7,
F692A8CB02555BA201FF60F7,
......@@ -273,6 +273,7 @@
F5BB2BC6030F772101FCFE1D,
933A349E038AE80F008635CE,
9374D3AA038D9D74008635CE,
931C6CF2038EE8DE008635CE,
);
isa = PBXSourcesBuildPhase;
runOnlyForDeploymentPostprocessing = 0;
......@@ -323,52 +324,54 @@
08FB77AEFE84172EC02AAC07 = {
children = (
938772E5038BFE19008635CE,
F692A84D0255597D01FF60F7,
F692A84E0255597D01FF60F7,
F692A84D0255597D01FF60F7,
F692A84F0255597D01FF60F7,
F692A8500255597D01FF60F7,
F692A8510255597D01FF60F7,
F692A8520255597D01FF60F7,
F692A8500255597D01FF60F7,
F692A8530255597D01FF60F7,
F5BB2BC4030F772101FCFE1D,
F692A8520255597D01FF60F7,
F5BB2BC5030F772101FCFE1D,
F5BB2BC4030F772101FCFE1D,
9373524E038DA8C2008635CE,
F692A8550255597D01FF60F7,
F692A8560255597D01FF60F7,
F692A8550255597D01FF60F7,
F692A8570255597D01FF60F7,
F692A8580255597D01FF60F7,
F692A8590255597D01FF60F7,
F692A85A0255597D01FF60F7,
F692A8580255597D01FF60F7,
F692A85B0255597D01FF60F7,
F692A85C0255597D01FF60F7,
F692A85A0255597D01FF60F7,
F692A85D0255597D01FF60F7,
F692A85E0255597D01FF60F7,
F692A85C0255597D01FF60F7,
F692A85F0255597D01FF60F7,
F692A85E0255597D01FF60F7,
933A349A038AE7C6008635CE,
933A349D038AE80F008635CE,
F692A8610255597D01FF60F7,
F692A8620255597D01FF60F7,
F692A8610255597D01FF60F7,
F692A8630255597D01FF60F7,
F692A8640255597D01FF60F7,
F692A8680255597D01FF60F7,
931C6CEF038EE8DE008635CE,
931C6CF0038EE8DE008635CE,
F692A8690255597D01FF60F7,
F692A86A0255597D01FF60F7,
F692A86B0255597D01FF60F7,
F692A86C0255597D01FF60F7,
F692A86D0255597D01FF60F7,
F692A86E0255597D01FF60F7,
F692A86D0255597D01FF60F7,
F5FFE656026B47A6018635CA,
F692A8700255597D01FF60F7,
F692A8710255597D01FF60F7,
F692A8700255597D01FF60F7,
F692A8720255597D01FF60F7,
F692A8730255597D01FF60F7,
F692A8740255597D01FF60F7,
F692A8750255597D01FF60F7,
F692A8730255597D01FF60F7,
F692A8760255597D01FF60F7,
F692A8770255597D01FF60F7,
F692A8750255597D01FF60F7,
F692A8780255597D01FF60F7,
F692A8790255597D01FF60F7,
F692A8770255597D01FF60F7,
F692A87A0255597D01FF60F7,
F692A8790255597D01FF60F7,
F5341390030CEEB1018BE7F3,
F5341391030CEEB1018BE7F3,
F54F0800030CD22001B5C2EB,
......@@ -384,7 +387,6 @@
F692A8800255597D01FF60F7,
F692A8810255597D01FF60F7,
F692A8840255597D01FF60F7,
F692A8830255597D01FF60F7,
F692A8860255597D01FF60F7,
F692A8850255597D01FF60F7,
F692A8880255597D01FF60F7,
......@@ -444,6 +446,33 @@
//932
//933
//934
931C6CEF038EE8DE008635CE = {
fileEncoding = 4;
isa = PBXFileReference;
path = list.h;
refType = 4;
};
931C6CF0038EE8DE008635CE = {
fileEncoding = 4;
isa = PBXFileReference;
path = list.cpp;
refType = 4;
};
931C6CF1038EE8DE008635CE = {
fileRef = 931C6CEF038EE8DE008635CE;
isa = PBXBuildFile;
settings = {
ATTRIBUTES = (
Private,
);
};
};
931C6CF2038EE8DE008635CE = {
fileRef = 931C6CF0038EE8DE008635CE;
isa = PBXBuildFile;
settings = {
};
};
933A3499038AE7C6008635CE = {
fileEncoding = 4;
isa = PBXFileReference;
......@@ -1043,12 +1072,6 @@
path = string_object.lut.h;
refType = 4;
};
F692A8830255597D01FF60F7 = {
fileEncoding = 30;
isa = PBXFileReference;
path = types.cpp;
refType = 4;
};
F692A8840255597D01FF60F7 = {
fileEncoding = 30;
isa = PBXFileReference;
......@@ -1433,12 +1456,6 @@
settings = {
};
};
F692A8BF0255597D01FF60F7 = {
fileRef = F692A8830255597D01FF60F7;
isa = PBXBuildFile;
settings = {
};
};
F692A8C00255597D01FF60F7 = {
fileRef = F692A8840255597D01FF60F7;
isa = PBXBuildFile;
......
......@@ -160,9 +160,7 @@ Value FunctionProtoFuncImp::call(ExecState *exec, Object &thisObj, const List &a
else
callThis = thisArg.toObject(exec);
List callArgs = args.copy();
callArgs.removeFirst();
result = func.call(exec,callThis,callArgs);
result = func.call(exec,callThis,args.copyTail());
}
break;
}
......
......@@ -21,8 +21,28 @@
#include "identifier.h"
#define DUMP_STATISTICS 0
namespace KJS {
#if DUMP_STATISTICS
static int numProbes;
static int numCollisions;
struct IdentifierStatisticsExitLogger { ~IdentifierStatisticsExitLogger(); };
static IdentifierStatisticsExitLogger logger;
IdentifierStatisticsExitLogger::~IdentifierStatisticsExitLogger()
{
printf("\nKJS::Identifier statistics\n\n");
printf("%d probes\n", numProbes);
printf("%d collisions (%.1f%%)\n", numCollisions, 100.0 * numCollisions / numProbes);
}
#endif
Identifier Identifier::null;
extern const Identifier argumentsPropertyName("arguments");
......@@ -92,6 +112,10 @@ UString::Rep *Identifier::add(const char *c)
unsigned hash = UString::Rep::computeHash(c);
int i = hash & _tableSizeMask;
#if DUMP_STATISTICS
++numProbes;
numCollisions += _table[i] && !equal(_table[i], c);
#endif
while (UString::Rep *key = _table[i]) {
if (equal(key, c))
return key;
......@@ -129,6 +153,10 @@ UString::Rep *Identifier::add(const UChar *s, int length)
unsigned hash = UString::Rep::computeHash(s, length);
int i = hash & _tableSizeMask;
#if DUMP_STATISTICS
++numProbes;
numCollisions += _table[i] && !equal(_table[i], s, length);
#endif
while (UString::Rep *key = _table[i]) {
if (equal(key, s, length))
return key;
......@@ -168,6 +196,10 @@ UString::Rep *Identifier::add(UString::Rep *r)
unsigned hash = r->hash();
int i = hash & _tableSizeMask;
#if DUMP_STATISTICS
++numProbes;
numCollisions += _table[i] && !equal(_table[i], r);
#endif
while (UString::Rep *key = _table[i]) {
if (equal(key, r))
return key;
......@@ -190,6 +222,10 @@ inline void Identifier::insert(UString::Rep *key)
unsigned hash = key->hash();
int i = hash & _tableSizeMask;
#if DUMP_STATISTICS
++numProbes;
numCollisions += _table[i] != 0;
#endif
while (_table[i])
i = (i + 1) & _tableSizeMask;
......@@ -203,6 +239,10 @@ void Identifier::remove(UString::Rep *r)
UString::Rep *key;
int i = hash & _tableSizeMask;
#if DUMP_STATISTICS
++numProbes;
numCollisions += _table[i] && equal(_table[i], r);
#endif
while ((key = _table[i])) {
if (equal(key, r))
break;
......
......@@ -36,6 +36,43 @@
#include "error_object.h"
#include "nodes.h"
#define DUMP_STATISTICS 0
#if DUMP_STATISTICS
static int numLists;
static int numListsHighWaterMark;
static int listSizeHighWaterMark;
static int numListsDestroyed;
static int numListsBiggerThan[17];
static int numNodesAllocated;
static int numNodesWouldNeedToBeCopied;
struct ListStatisticsExitLogger { ~ListStatisticsExitLogger(); };
static ListStatisticsExitLogger logger;
ListStatisticsExitLogger::~ListStatisticsExitLogger()
{
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");
}
}
#endif
namespace KJS {
struct ListNode {
......@@ -48,10 +85,18 @@ namespace KJS {
};
struct ListHookNode : public ListNode {
ListHookNode() : ListNode(0, this, this),
listRefCount(1), nodesRefCount(1) { }
ListHookNode() : ListNode(0, this, this), listRefCount(1), nodesRefCount(1)
#if DUMP_STATISTICS
, sizeHighWaterMark(0)
#endif
{ }
int listRefCount;
int nodesRefCount;
#if DUMP_STATISTICS
int sizeHighWaterMark;
#endif
};
// ------------------------------ ListIterator ---------------------------------
......@@ -96,10 +141,20 @@ Value ListIterator::operator--(int)
List::List() : hook(new ListHookNode)
{
#if DUMP_STATISTICS
if (++numLists > numListsHighWaterMark)
numListsHighWaterMark = numLists;
#endif
}
List::List(const List& l) : hook(l.hook)
{
#if DUMP_STATISTICS
if (++numLists > numListsHighWaterMark)
numListsHighWaterMark = numLists;
numNodesWouldNeedToBeCopied += size();
#endif
++hook->listRefCount;
if (hook->nodesRefCount++ == 0)
refAll();
......@@ -113,26 +168,27 @@ List& List::operator=(const List& l)
List::~List()
{
#if DUMP_STATISTICS
--numLists;
#endif
if (--hook->nodesRefCount == 0)
derefAll();
if (--hook->listRefCount == 0) {
#if DUMP_STATISTICS
++numListsDestroyed;
for (int i = 0; i < 17; i++)
if (hook->sizeHighWaterMark > i)
++numListsBiggerThan[i];
#endif
assert(hook->nodesRefCount == 0);
clearInternal();
delete hook;
}
}
void List::mark()
{
ListNode *n = hook->next;
while (n != hook) {
if (!n->member->marked())
n->member->mark();
n = n->next;
}
}
void List::append(const Value& val)
{
ListNode *n = new ListNode(val, hook->prev, hook);
......@@ -140,6 +196,16 @@ void List::append(const Value& val)
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
}
void List::append(ValueImp *val)
......@@ -149,8 +215,20 @@ void List::append(ValueImp *val)
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);
......@@ -158,8 +236,20 @@ void List::prepend(const Value& val)
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);
......@@ -167,6 +257,16 @@ void List::prepend(ValueImp *val)
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)
......@@ -184,6 +284,8 @@ void List::removeFirst()
erase(hook->next);
}
#if 0
void List::removeLast()
{
erase(hook->prev);
......@@ -200,6 +302,8 @@ void List::remove(const Value &val)
}
}
#endif
void List::clear()
{
if (hook->nodesRefCount)
......
/*
* 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)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
*/
#ifndef KJS_LIST_H
#define KJS_LIST_H
#include "value.h"
namespace KJS {
class List;
class ListIterator;
class ListNode;
class ListHookNode;
/**
* @short Iterator for @ref KJS::List objects.
*/
class ListIterator {
friend class List;
ListIterator() : node(0) { }
ListIterator(ListNode *n) : node(n) { }
public:
/**
* Construct an iterator that points to the first element of the list.
* @param l The list the iterator will operate on.
*/
ListIterator(const List &l);
/**
* Dereference the iterator.
* @return A pointer to the element the iterator operates on.
*/
ValueImp* operator->() const;
Value operator*() const;
/**
* Postfix increment operator.
* @return The element after the increment.
*/
Value operator++();
/**
* Prefix increment operator.
*/
Value operator++(int);
/**
* Postfix decrement operator.
*/
Value operator--();
/**
* Prefix decrement operator.
*/
Value operator--(int);
/**
* Compare the iterator with another one.
* @return True if the two iterators operate on the same list element.
* False otherwise.
*/
bool operator==(const ListIterator &it) const { return node == it.node; }
/**
* Check for inequality with another iterator.
* @return True if the two iterators operate on different list elements.
*/
bool operator!=(const ListIterator &it) const { return node != it.node; }
private:
ListNode *node;
};
/**
* @short Native list type.
*
* List is a native ECMAScript type. List values are only used for
* intermediate results of expression evaluation and cannot be stored
* as properties of objects.
*
* The list is explicitly shared. Note that while copy() returns a
* copy of the list the referenced objects are still shared.
*/
class List {
friend class ListIterator;
public:
List();
List(const List& l);
List &operator=(const List& l);
~List();
List copyTail() const { List result = copy(); result.removeFirst(); return result; }
/**
* Append an object to the end of the list.
*
* @param val Pointer to object.
*/
void append(const Value& val);
void append(ValueImp *val);
/**