Commit df5526f8 authored by mjs's avatar mjs

Reviewed by Oliver.

        - fold together toPrimitive() and toNumber() conversions for 0.5% gain on SunSpider

        * kjs/nodes.cpp:
        (KJS::SubNode::evaluate): Subtract directly, since toPrimitive() is not
        adding any value over toNumber() here.
        (KJS::valueForReadModifyAssignment): Ditto.
        (KJS::lessThan): Use new getPrimitiveNumber() method to avoid some virtual calls
        and branches.
        (KJS::lessThanEq): Ditto.
        * JavaScriptCore.exp: Export new functions as needed.
        * kjs/value.h:
        (KJS::JSValue::toPrimitive): Fixed formatting.
        (KJS::JSValue::getPrimitiveNumber): New method - this simultaneously converts
        to number and tells you whether a toPrimitive() conversion with a Number hint
        would have given a string.
        * kjs/internal.cpp:
        (KJS::StringImp::getPrimitiveNumber): Implemented. 
        (KJS::NumberImp::getPrimitiveNumber): ditto
        (KJS::GetterSetterImp::getPrimitiveNumber): ditto
        (KJS::StringImp::toPrimitive): Fixed formatting.
        (KJS::NumberImp::toPrimitive): ditto
        (KJS::GetterSetterImp::toPrimitive): ditto
        * kjs/internal.h:
        * kjs/object.cpp:
        (KJS::JSObject::getPrimitiveNumber): Implemented.
        * kjs/object.h:



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@27086 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 50eb4b67
2007-10-25 Maciej Stachowiak <mjs@apple.com>
Reviewed by Oliver.
- fold together toPrimitive() and toNumber() conversions for 0.5% gain on SunSpider
* kjs/nodes.cpp:
(KJS::SubNode::evaluate): Subtract directly, since toPrimitive() is not
adding any value over toNumber() here.
(KJS::valueForReadModifyAssignment): Ditto.
(KJS::lessThan): Use new getPrimitiveNumber() method to avoid some virtual calls
and branches.
(KJS::lessThanEq): Ditto.
* JavaScriptCore.exp: Export new functions as needed.
* kjs/value.h:
(KJS::JSValue::toPrimitive): Fixed formatting.
(KJS::JSValue::getPrimitiveNumber): New method - this simultaneously converts
to number and tells you whether a toPrimitive() conversion with a Number hint
would have given a string.
* kjs/internal.cpp:
(KJS::StringImp::getPrimitiveNumber): Implemented.
(KJS::NumberImp::getPrimitiveNumber): ditto
(KJS::GetterSetterImp::getPrimitiveNumber): ditto
(KJS::StringImp::toPrimitive): Fixed formatting.
(KJS::NumberImp::toPrimitive): ditto
(KJS::GetterSetterImp::toPrimitive): ditto
* kjs/internal.h:
* kjs/object.cpp:
(KJS::JSObject::getPrimitiveNumber): Implemented.
* kjs/object.h:
2007-10-25 Sam Weinig <sam@webkit.org>
Reviewed by Adam Roben.
......
......@@ -123,8 +123,8 @@ __ZN3KJS11Interpreter6s_hookE
__ZN3KJS11Interpreter8evaluateERKNS_7UStringEiPKNS_5UCharEiPNS_7JSValueE
__ZN3KJS11Interpreter8evaluateERKNS_7UStringEiS3_PNS_7JSValueE
__ZN3KJS11InterpreterC1EPNS_14JSGlobalObjectE
__ZN3KJS11InterpreterC2EPNS_14JSGlobalObjectE
__ZN3KJS11InterpreterC1Ev
__ZN3KJS11InterpreterC2EPNS_14JSGlobalObjectE
__ZN3KJS11InterpreterD1Ev
__ZN3KJS11InterpreterD2Ev
__ZN3KJS11JSImmediate4typeEPKNS_7JSValueE
......@@ -264,6 +264,7 @@ __ZNK3KJS8Bindings8Instance10rootObjectEv
__ZNK3KJS8JSObject11hasPropertyEPNS_9ExecStateERKNS_10IdentifierE
__ZNK3KJS8JSObject12defaultValueEPNS_9ExecStateENS_6JSTypeE
__ZNK3KJS8JSObject14implementsCallEv
__ZNK3KJS8JSObject18getPrimitiveNumberEPNS_9ExecStateERd
__ZNK3KJS8JSObject19implementsConstructEv
__ZNK3KJS8JSObject21implementsHasInstanceEv
__ZNK3KJS8JSObject3getEPNS_9ExecStateERKNS_10IdentifierE
......
......@@ -55,9 +55,15 @@ namespace KJS {
// ------------------------------ StringImp ------------------------------------
JSValue *StringImp::toPrimitive(ExecState *, JSType) const
JSValue* StringImp::toPrimitive(ExecState*, JSType) const
{
return const_cast<StringImp *>(this);
return const_cast<StringImp*>(this);
}
bool StringImp::getPrimitiveNumber(ExecState*, double& number) const
{
number = val.toDouble();
return false;
}
bool StringImp::toBoolean(ExecState *) const
......@@ -82,9 +88,15 @@ JSObject* StringImp::toObject(ExecState *exec) const
// ------------------------------ NumberImp ------------------------------------
JSValue *NumberImp::toPrimitive(ExecState *, JSType) const
JSValue* NumberImp::toPrimitive(ExecState*, JSType) const
{
return const_cast<NumberImp *>(this);
return const_cast<NumberImp*>(this);
}
bool NumberImp::getPrimitiveNumber(ExecState*, double& number) const
{
number = val;
return true;
}
bool NumberImp::toBoolean(ExecState *) const
......@@ -144,12 +156,19 @@ void GetterSetterImp::mark()
setter->mark();
}
JSValue *GetterSetterImp::toPrimitive(ExecState*, JSType) const
JSValue* GetterSetterImp::toPrimitive(ExecState*, JSType) const
{
ASSERT(false);
return jsNull();
}
bool GetterSetterImp::getPrimitiveNumber(ExecState*, double& number) const
{
ASSERT(false);
number = 0;
return true;
}
bool GetterSetterImp::toBoolean(ExecState*) const
{
ASSERT(false);
......
......@@ -53,7 +53,8 @@ namespace KJS {
JSType type() const { return StringType; }
JSValue *toPrimitive(ExecState *exec, JSType preferred = UnspecifiedType) const;
JSValue* toPrimitive(ExecState*, JSType preferred = UnspecifiedType) const;
bool getPrimitiveNumber(ExecState*, double& number) const;
bool toBoolean(ExecState *exec) const;
double toNumber(ExecState *exec) const;
UString toString(ExecState *exec) const;
......@@ -71,7 +72,8 @@ namespace KJS {
JSType type() const { return NumberType; }
JSValue *toPrimitive(ExecState *exec, JSType preferred = UnspecifiedType) const;
JSValue* toPrimitive(ExecState*, JSType preferred = UnspecifiedType) const;
bool getPrimitiveNumber(ExecState*, double& number) const;
bool toBoolean(ExecState *exec) const;
double toNumber(ExecState *exec) const;
UString toString(ExecState *exec) const;
......
......@@ -1240,14 +1240,6 @@ static inline JSValue *add(ExecState *exec, JSValue *v1, JSValue *v2)
return jsNumber(p1->toNumber(exec) + p2->toNumber(exec));
}
static inline JSValue *sub(ExecState *exec, JSValue *v1, JSValue *v2)
{
JSValue *p1 = v1->toPrimitive(exec, NumberType);
JSValue *p2 = v2->toPrimitive(exec, NumberType);
return jsNumber(p1->toNumber(exec) - p2->toNumber(exec));
}
// ECMA 11.6.1
JSValue *AddNode::evaluate(ExecState *exec)
{
......@@ -1270,7 +1262,7 @@ JSValue *SubNode::evaluate(ExecState *exec)
JSValue *v2 = term2->evaluate(exec);
KJS_CHECKEXCEPTIONVALUE
return sub(exec, v1, v2);
return jsNumber(v1->toNumber(exec) - v2->toNumber(exec));
}
// ------------------------------ Shift Nodes ------------------------------------
......@@ -1318,24 +1310,28 @@ JSValue *UnsignedRightShiftNode::evaluate(ExecState *exec)
static inline JSValue* lessThan(ExecState *exec, JSValue* v1, JSValue* v2)
{
JSValue *p1 = v1->toPrimitive(exec, NumberType);
JSValue *p2 = v2->toPrimitive(exec, NumberType);
if (p1->isString() && p2->isString())
return jsBoolean(p1->toString(exec) < p2->toString(exec));
double n1;
double n2;
bool wasNotString1 = v1->getPrimitiveNumber(exec, n1);
bool wasNotString2 = v2->getPrimitiveNumber(exec, n2);
return jsBoolean(p1->toNumber(exec) < p2->toNumber(exec));
if (wasNotString1 | wasNotString2)
return jsBoolean(n1 < n2);
return jsBoolean(v1->toString(exec) < v2->toString(exec));
}
static inline JSValue* lessThanEq(ExecState *exec, JSValue* v1, JSValue* v2)
{
JSValue *p1 = v1->toPrimitive(exec, NumberType);
JSValue *p2 = v2->toPrimitive(exec, NumberType);
double n1;
double n2;
bool wasNotString1 = v1->getPrimitiveNumber(exec, n1);
bool wasNotString2 = v2->getPrimitiveNumber(exec, n2);
if (p1->isString() && p2->isString())
return jsBoolean(!(p2->toString(exec) < p1->toString(exec)));
if (wasNotString1 | wasNotString2)
return jsBoolean(n1 <= n2);
return jsBoolean(p1->toNumber(exec) <= p2->toNumber(exec));
return jsBoolean(!(v2->toString(exec) < v1->toString(exec)));
}
// ECMA 11.8.1
......@@ -1564,7 +1560,7 @@ static ALWAYS_INLINE JSValue *valueForReadModifyAssignment(ExecState * exec, JSV
v = add(exec, v1, v2);
break;
case OpMinusEq:
v = sub(exec, v1, v2);
v = jsNumber(v1->toNumber(exec) - v2->toNumber(exec));
break;
case OpLShift:
i1 = v1->toInt32(exec);
......
......@@ -354,6 +354,13 @@ static ALWAYS_INLINE JSValue *tryGetAndCallProperty(ExecState *exec, const JSObj
return NULL;
}
bool JSObject::getPrimitiveNumber(ExecState* exec, double& number) const
{
JSValue* result = defaultValue(exec, NumberType);
number = result->toNumber(exec);
return !result->isString();
}
// ECMA 8.6.2.6
JSValue* JSObject::defaultValue(ExecState* exec, JSType hint) const
{
......
......@@ -83,7 +83,8 @@ namespace KJS {
GetterSetterImp() : getter(0), setter(0) { }
virtual JSValue *toPrimitive(ExecState *exec, JSType preferred = UnspecifiedType) const;
virtual JSValue* toPrimitive(ExecState*, JSType preferred = UnspecifiedType) const;
virtual bool getPrimitiveNumber(ExecState*, double& number) const;
virtual bool toBoolean(ExecState *exec) const;
virtual double toNumber(ExecState *exec) const;
virtual UString toString(ExecState *exec) const;
......@@ -416,7 +417,8 @@ namespace KJS {
virtual void getPropertyNames(ExecState*, PropertyNameArray&);
virtual JSValue *toPrimitive(ExecState *exec, JSType preferredType = UnspecifiedType) const;
virtual JSValue* toPrimitive(ExecState*, JSType preferredType = UnspecifiedType) const;
virtual bool getPrimitiveNumber(ExecState*, double& number) const;
virtual bool toBoolean(ExecState *exec) const;
virtual double toNumber(ExecState *exec) const;
virtual UString toString(ExecState *exec) const;
......
......@@ -81,7 +81,9 @@ public:
bool getTruncatedUInt32(uint32_t&) const;
// Basic conversions.
JSValue *toPrimitive(ExecState *exec, JSType preferredType = UnspecifiedType) const;
JSValue* toPrimitive(ExecState* exec, JSType preferredType = UnspecifiedType) const;
bool getPrimitiveNumber(ExecState* exec, double& number) const;
bool toBoolean(ExecState *exec) const;
double toNumber(ExecState *exec) const;
UString toString(ExecState *exec) const;
......@@ -147,6 +149,7 @@ public:
// Basic conversions.
virtual JSValue *toPrimitive(ExecState *exec, JSType preferredType = UnspecifiedType) const = 0;
virtual bool getPrimitiveNumber(ExecState* exec, double& number) const = 0;
virtual bool toBoolean(ExecState *exec) const = 0;
virtual double toNumber(ExecState *exec) const = 0;
virtual UString toString(ExecState *exec) const = 0;
......@@ -365,9 +368,18 @@ inline JSType JSValue::type() const
return JSImmediate::isImmediate(this) ? JSImmediate::type(this) : asCell()->type();
}
inline JSValue *JSValue::toPrimitive(ExecState *exec, JSType preferredType) const
inline JSValue* JSValue::toPrimitive(ExecState* exec, JSType preferredType) const
{
return JSImmediate::isImmediate(this) ? const_cast<JSValue*>(this) : asCell()->toPrimitive(exec, preferredType);
}
inline bool JSValue::getPrimitiveNumber(ExecState* exec, double& number) const
{
return JSImmediate::isImmediate(this) ? const_cast<JSValue *>(this) : asCell()->toPrimitive(exec, preferredType);
if (JSImmediate::isImmediate(this)) {
number = JSImmediate::toDouble(this);
return true;
}
return asCell()->getPrimitiveNumber(exec, number);
}
inline bool JSValue::toBoolean(ExecState *exec) const
......
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