Commit 401641ee authored by darin's avatar darin

- fix worst speed problems on the sort page of the iBench JavaScript test

	Sped up JavaScript iBench by 70%, the sort page by 88%.

        * kjs/array_object.h: Add array-specific sort functions.
        * kjs/array_object.cpp:
        (compareByStringForQSort): Added.
        (ArrayInstanceImp::sort): Added.
        (compareWithCompareFunctionForQSort): Added.
        (ArrayProtoFuncImp::call): Use ArrayInstanceImp::sort if the object being
	sorted is actually an array.

        * kjs/object.h: Add argumentsPropertyName.
        * kjs/object.cpp: Add argumentsPropertyName.
        * kjs/function.cpp:
        (FunctionImp::FunctionImp): Use argumentsPropertyName to avoid making a UString.
        (FunctionImp::call): Ditto.
        (ActivationImp::ActivationImp): Ditto.
        * kjs/function_object.cpp: (FunctionObjectImp::construct): Ditto.

        * kjs/ustring.h: Added compare function for -1/0/+1 comparison.
        * kjs/ustring.cpp: (KJS::compare): Added.


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@2736 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent a34e69ca
2002-11-18 Darin Adler <darin@apple.com>
- fix worst speed problems on the sort page of the iBench JavaScript test
Sped up JavaScript iBench by 70%, the sort page by 88%.
* kjs/array_object.h: Add array-specific sort functions.
* kjs/array_object.cpp:
(compareByStringForQSort): Added.
(ArrayInstanceImp::sort): Added.
(compareWithCompareFunctionForQSort): Added.
(ArrayProtoFuncImp::call): Use ArrayInstanceImp::sort if the object being
sorted is actually an array.
* kjs/object.h: Add argumentsPropertyName.
* kjs/object.cpp: Add argumentsPropertyName.
* kjs/function.cpp:
(FunctionImp::FunctionImp): Use argumentsPropertyName to avoid making a UString.
(FunctionImp::call): Ditto.
(ActivationImp::ActivationImp): Ditto.
* kjs/function_object.cpp: (FunctionObjectImp::construct): Ditto.
* kjs/ustring.h: Added compare function for -1/0/+1 comparison.
* kjs/ustring.cpp: (KJS::compare): Added.
2002-11-18 Maciej Stachowiak <mjs@apple.com>
Change ArgumentListNode operations to be iterative instead of
......
2002-11-18 Darin Adler <darin@apple.com>
- fix worst speed problems on the sort page of the iBench JavaScript test
Sped up JavaScript iBench by 70%, the sort page by 88%.
* kjs/array_object.h: Add array-specific sort functions.
* kjs/array_object.cpp:
(compareByStringForQSort): Added.
(ArrayInstanceImp::sort): Added.
(compareWithCompareFunctionForQSort): Added.
(ArrayProtoFuncImp::call): Use ArrayInstanceImp::sort if the object being
sorted is actually an array.
* kjs/object.h: Add argumentsPropertyName.
* kjs/object.cpp: Add argumentsPropertyName.
* kjs/function.cpp:
(FunctionImp::FunctionImp): Use argumentsPropertyName to avoid making a UString.
(FunctionImp::call): Ditto.
(ActivationImp::ActivationImp): Ditto.
* kjs/function_object.cpp: (FunctionObjectImp::construct): Ditto.
* kjs/ustring.h: Added compare function for -1/0/+1 comparison.
* kjs/ustring.cpp: (KJS::compare): Added.
2002-11-18 Maciej Stachowiak <mjs@apple.com>
Change ArgumentListNode operations to be iterative instead of
......
2002-11-18 Darin Adler <darin@apple.com>
- fix worst speed problems on the sort page of the iBench JavaScript test
Sped up JavaScript iBench by 70%, the sort page by 88%.
* kjs/array_object.h: Add array-specific sort functions.
* kjs/array_object.cpp:
(compareByStringForQSort): Added.
(ArrayInstanceImp::sort): Added.
(compareWithCompareFunctionForQSort): Added.
(ArrayProtoFuncImp::call): Use ArrayInstanceImp::sort if the object being
sorted is actually an array.
* kjs/object.h: Add argumentsPropertyName.
* kjs/object.cpp: Add argumentsPropertyName.
* kjs/function.cpp:
(FunctionImp::FunctionImp): Use argumentsPropertyName to avoid making a UString.
(FunctionImp::call): Ditto.
(ActivationImp::ActivationImp): Ditto.
* kjs/function_object.cpp: (FunctionObjectImp::construct): Ditto.
* kjs/ustring.h: Added compare function for -1/0/+1 comparison.
* kjs/ustring.cpp: (KJS::compare): Added.
2002-11-18 Maciej Stachowiak <mjs@apple.com>
Change ArgumentListNode operations to be iterative instead of
......
......@@ -192,6 +192,55 @@ void ArrayInstanceImp::mark()
}
}
static ExecState *execForCompareByStringForQSort;
static int compareByStringForQSort(const void *a, const void *b)
{
ExecState *exec = execForCompareByStringForQSort;
return compare(Value(*(ValueImp **)a).toString(exec), Value(*(ValueImp **)b).toString(exec));
}
void ArrayInstanceImp::sort(ExecState *exec)
{
execForCompareByStringForQSort = exec;
qsort(storage, length, sizeof(ValueImp *), compareByStringForQSort);
execForCompareByStringForQSort = 0;
}
struct CompareWithCompareFunctionArguments {
CompareWithCompareFunctionArguments(ExecState *e, ObjectImp *cf)
: exec(e)
, compareFunction(cf)
, globalObject(e->interpreter()->globalObject())
{ }
ExecState *exec;
ObjectImp *compareFunction;
List arguments;
Object globalObject;
};
static CompareWithCompareFunctionArguments *compareWithCompareFunctionArguments;
static int compareWithCompareFunctionForQSort(const void *a, const void *b)
{
CompareWithCompareFunctionArguments *args = compareWithCompareFunctionArguments;
args->arguments.clear();
args->arguments.append(Value(*(ValueImp **)a));
args->arguments.append(Value(*(ValueImp **)b));
return args->compareFunction->call(args->exec, args->globalObject, args->arguments)
.toInt32(args->exec);
}
void ArrayInstanceImp::sort(ExecState *exec, Object &compareFunction)
{
CompareWithCompareFunctionArguments args(exec, compareFunction.imp());
compareWithCompareFunctionArguments = &args;
qsort(storage, length, sizeof(ValueImp *), compareWithCompareFunctionForQSort);
compareWithCompareFunctionArguments = 0;
}
// ------------------------------ ArrayPrototypeImp ----------------------------
const ClassInfo ArrayPrototypeImp::info = {"Array", &ArrayInstanceImp::info, &arrayTable, 0};
......@@ -424,10 +473,19 @@ Value ArrayProtoFuncImp::call(ExecState *exec, Object &thisObj, const List &args
if (!sortFunction.implementsCall())
useSortFunction = false;
}
if (thisObj.imp()->classInfo() == &ArrayInstanceImp::info) {
if (useSortFunction)
((ArrayInstanceImp *)thisObj.imp())->sort(exec, sortFunction);
else
((ArrayInstanceImp *)thisObj.imp())->sort(exec);
result = thisObj;
break;
}
if (length == 0) {
thisObj.put(exec, lengthPropertyName, Number(0), DontEnum | DontDelete);
result = Undefined();
result = thisObj;
break;
}
......
......@@ -49,6 +49,9 @@ namespace KJS {
unsigned getLength() const { return length; }
void sort(ExecState *exec);
void sort(ExecState *exec, Object &compareFunction);
private:
void setLength(unsigned newLength);
......
......@@ -59,7 +59,7 @@ FunctionImp::FunctionImp(ExecState *exec, const UString &n)
{
Value protect(this);
//fprintf(stderr,"FunctionImp::FunctionImp this=%p\n");
put(exec,"arguments",Null(),ReadOnly|DontDelete|DontEnum);
put(exec,argumentsPropertyName,Null(),ReadOnly|DontDelete|DontEnum);
}
FunctionImp::~FunctionImp()
......@@ -108,12 +108,12 @@ Value FunctionImp::call(ExecState *exec, Object &thisObj, const List &args)
// value from a possible earlier call. Upon return, we restore the
// previous arguments object.
// Note: this does not appear to be part of the spec
Value oldArgs = get(&newExec, "arguments");
Value oldArgs = get(&newExec, argumentsPropertyName);
if (codeType() == FunctionCode) {
assert(ctx.activationObject().inherits(&ActivationImp::info));
Object argsObj = static_cast<ActivationImp*>(ctx.activationObject().imp())->argumentsObject();
put(&newExec, "arguments", argsObj, DontDelete|DontEnum|ReadOnly);
put(&newExec, argumentsPropertyName, argsObj, DontDelete|DontEnum|ReadOnly);
}
// assign user supplied arguments to parameters
......@@ -127,7 +127,7 @@ Value FunctionImp::call(ExecState *exec, Object &thisObj, const List &args)
if (newExec.hadException())
exec->setException(newExec.exception());
if (codeType() == FunctionCode)
put(&newExec, "arguments", oldArgs, DontDelete|DontEnum|ReadOnly);
put(&newExec, argumentsPropertyName, oldArgs, DontDelete|DontEnum|ReadOnly);
#ifdef KJS_VERBOSE
if (comp.complType() == Throw)
......@@ -308,7 +308,7 @@ ActivationImp::ActivationImp(ExecState *exec, FunctionImp *f, const List &args)
{
Value protect(this);
arguments = new ArgumentsImp(exec,f, args);
put(exec, "arguments", Object(arguments), Internal|DontDelete);
put(exec, argumentsPropertyName, Object(arguments), Internal|DontDelete);
}
ActivationImp::~ActivationImp()
......
......@@ -283,7 +283,7 @@ Object FunctionObjectImp::construct(ExecState *exec, const List &args)
prototype.put(exec, "constructor",
Object(fimp), DontEnum|DontDelete|ReadOnly);
fimp->put(exec,prototypePropertyName,prototype,DontEnum|DontDelete|ReadOnly);
fimp->put(exec,"arguments",Null(),DontEnum|DontDelete|ReadOnly);
fimp->put(exec,argumentsPropertyName,Null(),DontEnum|DontDelete|ReadOnly);
return ret;
}
......
......@@ -41,6 +41,7 @@
namespace KJS {
extern const UString argumentsPropertyName("arguments");
extern const UString lengthPropertyName("length");
extern const UString prototypePropertyName("prototype");
extern const UString toStringPropertyName("toString");
......
......@@ -705,6 +705,7 @@ namespace KJS {
inline void Object::setInternalValue(const Value &v)
{ imp()->setInternalValue(v); }
extern const UString argumentsPropertyName;
extern const UString lengthPropertyName;
extern const UString prototypePropertyName;
extern const UString toStringPropertyName;
......
......@@ -642,3 +642,25 @@ bool KJS::operator<(const UString& s1, const UString& s2)
return (l1 < l2);
}
int KJS::compare(const UString& s1, const UString& s2)
{
const int l1 = s1.size();
const int l2 = s2.size();
const int lmin = l1 < l2 ? l1 : l2;
const UChar *c1 = s1.data();
const UChar *c2 = s2.data();
int l = 0;
while (l < lmin && *c1 == *c2) {
c1++;
c2++;
l++;
}
if (l < lmin)
return (c1->unicode() > c2->unicode()) ? 1 : -1;
if (l1 == l2) {
return 0;
}
return (l1 < l2) ? 1 : -1;
}
......@@ -430,6 +430,8 @@ namespace KJS {
inline UString operator+(const UString& s1, const UString& s2) {
return UString(s1, s2);
}
int compare(const UString &, const UString &);
}; // namespace
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment