Commit 349e1eb0 authored by darin@apple.com's avatar darin@apple.com

JavaScriptCore:

2008-08-12  Darin Adler  <darin@apple.com>

        Reviewed by Geoff.

        - eliminate JSValue::type()

        This will make it slightly easier to change the JSImmediate design without
        having to touch so many call sites.

        SunSpider says this change is a wash (looked like a slight speedup, but not
        statistically significant).

        * API/JSStringRef.cpp: Removed include of JSType.h.
        * API/JSValueRef.cpp: Removed include of JSType.h.
        (JSValueGetType): Replaced use of JSValue::type() with
        JSValue::is functions.

        * JavaScriptCore.exp: Updated.

        * VM/JSPropertyNameIterator.cpp: Removed type() implementation.
        (KJS::JSPropertyNameIterator::toPrimitive): Changed to take
        PreferredPrimitiveType argument instead of JSType.
        * VM/JSPropertyNameIterator.h: Ditto.

        * VM/Machine.cpp:
        (KJS::fastIsNumber): Updated for name change.
        (KJS::fastToInt32): Ditto.
        (KJS::fastToUInt32): Ditto.
        (KJS::jsAddSlowCase): Updated toPrimitive caller for change from
        JSType to PreferredPrimitiveType.
        (KJS::jsAdd): Replaced calls to JSValue::type() with calls to
        JSValue::isString().
        (KJS::jsTypeStringForValue): Replaced calls to JSValue::type()
        with multiple calls to JSValue::is -- we could make this a
        virtual function instead if we want to have faster performance.
        (KJS::Machine::privateExecute): Renamed JSImmediate::toTruncatedUInt32
        to JSImmediate::getTruncatedUInt32 for consistency with other functions.
        Changed two calls of JSValue::type() to JSValue::isString().

        * kjs/GetterSetter.cpp:
        (KJS::GetterSetter::toPrimitive): Changed to take
        PreferredPrimitiveType argument instead of JSType.
        (KJS::GetterSetter::isGetterSetter): Added.
        * kjs/GetterSetter.h:

        * kjs/JSCell.cpp:
        (KJS::JSCell::isString): Added.
        (KJS::JSCell::isGetterSetter): Added.
        (KJS::JSCell::isObject): Added.

        * kjs/JSCell.h: Eliminated type function. Added isGetterSetter.
        Made isString and isObject virtual. Changed toPrimitive to take
        PreferredPrimitiveType argument instead of JSType.
        (KJS::JSCell::isNumber): Use Heap::isNumber for faster performance.
        (KJS::JSValue::isGetterSetter): Added.
        (KJS::JSValue::toPrimitive): Changed to take
        PreferredPrimitiveType argument instead of JSType.

        * kjs/JSImmediate.h: Removed JSValue::type() and replaced
        JSValue::toTruncatedUInt32 with JSValue::getTruncatedUInt32.
        (KJS::JSImmediate::isEitherImmediate): Added.

        * kjs/JSNotAnObject.cpp:
        (KJS::JSNotAnObject::toPrimitive): Changed to take
        PreferredPrimitiveType argument instead of JSType.
        * kjs/JSNotAnObject.h: Ditto.
        * kjs/JSNumberCell.cpp:
        (KJS::JSNumberCell::toPrimitive): Ditto.
        * kjs/JSNumberCell.h:
        (KJS::JSNumberCell::toInt32): Renamed from fastToInt32. There's no
        other "slow" version of this once you have a JSNumberCell, so there's
        no need for "fast" in the name. It's a feature that this hides the
        base class toInt32, which does the same job less efficiently (and has
        an additional ExecState argument).
        (KJS::JSNumberCell::toUInt32): Ditto.

        * kjs/JSObject.cpp:
        (KJS::callDefaultValueFunction): Use isGetterSetter instead of type.
        (KJS::JSObject::getPrimitiveNumber): Use PreferredPrimitiveType.
        (KJS::JSObject::defaultValue): Ditto.
        (KJS::JSObject::defineGetter): Use isGetterSetter.
        (KJS::JSObject::defineSetter): Ditto.
        (KJS::JSObject::lookupGetter): Ditto.
        (KJS::JSObject::lookupSetter): Ditto.
        (KJS::JSObject::toNumber): Use PreferredPrimitiveType.
        (KJS::JSObject::toString): Ditto.
        (KJS::JSObject::isObject): Added.

        * kjs/JSObject.h:
        (KJS::JSObject::inherits): Call the isObject from JSCell; it's now
        hidden by our override of isObject.
        (KJS::JSObject::getOwnPropertySlotForWrite): Use isGetterSetter
        instead of type.
        (KJS::JSObject::getOwnPropertySlot): Ditto.
        (KJS::JSObject::toPrimitive): Use PreferredPrimitiveType.

        * kjs/JSString.cpp:
        (KJS::JSString::toPrimitive): Use PreferredPrimitiveType.
        (KJS::JSString::isString): Added.
        * kjs/JSString.h: Ditto.

        * kjs/JSValue.h: Removed type(), added isGetterSetter(). Added
        PreferredPrimitiveType enum and used it as the argument for the
        toPrimitive function.
        (KJS::JSValue::getBoolean): Simplified a bit an removed a branch.

        * kjs/collector.cpp:
        (KJS::typeName): Changed to use JSCell::is functions instead of
        calling JSCell::type.

        * kjs/collector.h:
        (KJS::Heap::isNumber): Renamed from fastIsNumber.

        * kjs/nodes.h: Added now-needed include of JSType, since the type
        is used here to record types of values in the tree.

        * kjs/operations.cpp:
        (KJS::equal): Rewrote to no longer depend on type().
        (KJS::strictEqual): Ditto.

JavaScriptGlue:

2008-08-12  Darin Adler  <darin@apple.com>

        Reviewed by Geoff.

        - eliminate JSValue::type()

        * JSUtils.cpp:
        (KJSValueToCFTypeInternal): Replaced uses of JSValue::type() with
        JSValue::is functions.
        * UserObjectImp.cpp:
        (UserObjectImp::getOwnPropertySlot): Ditto.
        (UserObjectImp::toPrimitive): Take PreferredPrimitiveType argument
        instead of JSType argument.
        * UserObjectImp.h: Ditto.

WebCore:

2008-08-12  Darin Adler  <darin@apple.com>

        Reviewed by Geoff.

        - eliminate JSValue::type()

        * bridge/c/c_instance.cpp:
        (KJS::Bindings::CInstance::defaultValue): Take PreferredPrimitiveType
        argument instead of JSType argument. Removed unneeded code to handle
        boolean, since that's never passed.
        * bridge/c/c_instance.h: Ditto.

        * bridge/c/c_utility.cpp:
        (KJS::Bindings::convertValueToNPVariant): Use JSValue::is functions
        instead of JSValue::type(). Removed unneeded code to handle
        "unspecified".

        * bridge/jni/jni_instance.cpp:
        (JavaInstance::defaultValue): Take PreferredPrimitiveType argument
        instead of JSType argument. Removed unneeded code to handle boolean.
        * bridge/jni/jni_instance.h: Ditto.

        * bridge/jni/jni_jsobject.mm:
        (JavaJSObject::convertValueToJObject): Use JSValue::is functions
        instead of JSValue::type().

        * bridge/objc/objc_instance.h: Take PreferredPrimitiveType argument
        instead of JSType argument. Removed unused argument.
        * bridge/objc/objc_instance.mm:
        (ObjcInstance::getValueOfUndefinedField): Removed unused argument.
        (ObjcInstance::defaultValue): Take PreferredPrimitiveType argument
        instead of JSType argument. Removed unneeded code to handle boolean
        and another dead code path for unknown types.

        * bridge/objc/objc_runtime.h: Take PreferredPrimitiveType argument
        instead of JSType argument. Removed override of type() that caused
        the fallback object to return "UndefinedType" when there is no
        invokeUndefinedMethodFromWebScript:withArguments: method defined.
        That didn't accomplish much, since most checks for undefined don't
        ever call type().
        * bridge/objc/objc_runtime.mm:
        (ObjcFallbackObjectImp::defaultValue): Ditto.

        * bridge/qt/qt_instance.cpp:
        (KJS::Bindings::QtInstance::defaultValue): Take PreferredPrimitiveType
        argument instead of JSType argument. Removed unneeded code to handle
        boolean.
        * bridge/qt/qt_instance.h: Ditto.

        * bridge/runtime.h:
        (KJS::Bindings::Instance::getValueOfUndefinedField): Removed
        unsed argument.
        * bridge/runtime_object.cpp:
        (RuntimeObjectImp::defaultValue): Take PreferredPrimitiveType
        argument instead of JSType argument.
        * bridge/runtime_object.h: Ditto.

WebKit/mac:

2008-08-12  Darin Adler  <darin@apple.com>

        Reviewed by Geoff.

        - eliminate JSValue::type()

        * WebView/WebView.mm:
        (aeDescFromJSValue): Rewrite to use the JSValue::is functions instead
        of a switch on JSValue::type().

LayoutTests:

2008-08-12  Darin Adler  <darin@apple.com>

        Reviewed by Geoff.

        - added a test since I had to rewrite the == and === operators

        * fast/js/equality-expected.txt: Added.
        * fast/js/equality.html: Added.
        * fast/js/resources/equality.js: Added.



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@35830 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent af7f8384
......@@ -31,7 +31,6 @@
#include "APICast.h"
#include "JSCallbackObject.h"
#include <kjs/JSType.h>
#include <kjs/JSGlobalObject.h>
#include <kjs/JSString.h>
#include <kjs/operations.h>
......@@ -46,23 +45,18 @@
JSType JSValueGetType(JSContextRef, JSValueRef value)
{
KJS::JSValue* jsValue = toJS(value);
switch (jsValue->type()) {
case KJS::UndefinedType:
return kJSTypeUndefined;
case KJS::NullType:
return kJSTypeNull;
case KJS::BooleanType:
return kJSTypeBoolean;
case KJS::NumberType:
return kJSTypeNumber;
case KJS::StringType:
return kJSTypeString;
case KJS::ObjectType:
return kJSTypeObject;
default:
ASSERT(!"JSValueGetType: unknown type code.\n");
return kJSTypeUndefined;
}
if (jsValue->isUndefined())
return kJSTypeUndefined;
if (jsValue->isNull())
return kJSTypeNull;
if (jsValue->isBoolean())
return kJSTypeBoolean;
if (jsValue->isNumber())
return kJSTypeNumber;
if (jsValue->isString())
return kJSTypeString;
ASSERT(jsValue->isObject());
return kJSTypeObject;
}
using namespace KJS; // placed here to avoid conflict between KJS::JSType and JSType, above.
......
2008-08-12 Darin Adler <darin@apple.com>
Reviewed by Geoff.
- eliminate JSValue::type()
This will make it slightly easier to change the JSImmediate design without
having to touch so many call sites.
SunSpider says this change is a wash (looked like a slight speedup, but not
statistically significant).
* API/JSStringRef.cpp: Removed include of JSType.h.
* API/JSValueRef.cpp: Removed include of JSType.h.
(JSValueGetType): Replaced use of JSValue::type() with
JSValue::is functions.
* JavaScriptCore.exp: Updated.
* VM/JSPropertyNameIterator.cpp: Removed type() implementation.
(KJS::JSPropertyNameIterator::toPrimitive): Changed to take
PreferredPrimitiveType argument instead of JSType.
* VM/JSPropertyNameIterator.h: Ditto.
* VM/Machine.cpp:
(KJS::fastIsNumber): Updated for name change.
(KJS::fastToInt32): Ditto.
(KJS::fastToUInt32): Ditto.
(KJS::jsAddSlowCase): Updated toPrimitive caller for change from
JSType to PreferredPrimitiveType.
(KJS::jsAdd): Replaced calls to JSValue::type() with calls to
JSValue::isString().
(KJS::jsTypeStringForValue): Replaced calls to JSValue::type()
with multiple calls to JSValue::is -- we could make this a
virtual function instead if we want to have faster performance.
(KJS::Machine::privateExecute): Renamed JSImmediate::toTruncatedUInt32
to JSImmediate::getTruncatedUInt32 for consistency with other functions.
Changed two calls of JSValue::type() to JSValue::isString().
* kjs/GetterSetter.cpp:
(KJS::GetterSetter::toPrimitive): Changed to take
PreferredPrimitiveType argument instead of JSType.
(KJS::GetterSetter::isGetterSetter): Added.
* kjs/GetterSetter.h:
* kjs/JSCell.cpp:
(KJS::JSCell::isString): Added.
(KJS::JSCell::isGetterSetter): Added.
(KJS::JSCell::isObject): Added.
* kjs/JSCell.h: Eliminated type function. Added isGetterSetter.
Made isString and isObject virtual. Changed toPrimitive to take
PreferredPrimitiveType argument instead of JSType.
(KJS::JSCell::isNumber): Use Heap::isNumber for faster performance.
(KJS::JSValue::isGetterSetter): Added.
(KJS::JSValue::toPrimitive): Changed to take
PreferredPrimitiveType argument instead of JSType.
* kjs/JSImmediate.h: Removed JSValue::type() and replaced
JSValue::toTruncatedUInt32 with JSValue::getTruncatedUInt32.
(KJS::JSImmediate::isEitherImmediate): Added.
* kjs/JSNotAnObject.cpp:
(KJS::JSNotAnObject::toPrimitive): Changed to take
PreferredPrimitiveType argument instead of JSType.
* kjs/JSNotAnObject.h: Ditto.
* kjs/JSNumberCell.cpp:
(KJS::JSNumberCell::toPrimitive): Ditto.
* kjs/JSNumberCell.h:
(KJS::JSNumberCell::toInt32): Renamed from fastToInt32. There's no
other "slow" version of this once you have a JSNumberCell, so there's
no need for "fast" in the name. It's a feature that this hides the
base class toInt32, which does the same job less efficiently (and has
an additional ExecState argument).
(KJS::JSNumberCell::toUInt32): Ditto.
* kjs/JSObject.cpp:
(KJS::callDefaultValueFunction): Use isGetterSetter instead of type.
(KJS::JSObject::getPrimitiveNumber): Use PreferredPrimitiveType.
(KJS::JSObject::defaultValue): Ditto.
(KJS::JSObject::defineGetter): Use isGetterSetter.
(KJS::JSObject::defineSetter): Ditto.
(KJS::JSObject::lookupGetter): Ditto.
(KJS::JSObject::lookupSetter): Ditto.
(KJS::JSObject::toNumber): Use PreferredPrimitiveType.
(KJS::JSObject::toString): Ditto.
(KJS::JSObject::isObject): Added.
* kjs/JSObject.h:
(KJS::JSObject::inherits): Call the isObject from JSCell; it's now
hidden by our override of isObject.
(KJS::JSObject::getOwnPropertySlotForWrite): Use isGetterSetter
instead of type.
(KJS::JSObject::getOwnPropertySlot): Ditto.
(KJS::JSObject::toPrimitive): Use PreferredPrimitiveType.
* kjs/JSString.cpp:
(KJS::JSString::toPrimitive): Use PreferredPrimitiveType.
(KJS::JSString::isString): Added.
* kjs/JSString.h: Ditto.
* kjs/JSValue.h: Removed type(), added isGetterSetter(). Added
PreferredPrimitiveType enum and used it as the argument for the
toPrimitive function.
(KJS::JSValue::getBoolean): Simplified a bit an removed a branch.
* kjs/collector.cpp:
(KJS::typeName): Changed to use JSCell::is functions instead of
calling JSCell::type.
* kjs/collector.h:
(KJS::Heap::isNumber): Renamed from fastIsNumber.
* kjs/nodes.h: Added now-needed include of JSType, since the type
is used here to record types of values in the tree.
* kjs/operations.cpp:
(KJS::equal): Rewrote to no longer depend on type().
(KJS::strictEqual): Ditto.
2008-08-18 Kevin McCullough <kmccullough@apple.com>
Reviewed by Tim.
......
......@@ -275,8 +275,11 @@ __ZNK3KJS17DebuggerCallFrame8evaluateERKNS_7UStringERPNS_7JSValueE
__ZNK3KJS4Node8toStringEv
__ZNK3KJS6JSCell12toThisObjectEPNS_9ExecStateE
__ZNK3KJS6JSCell12toThisStringEPNS_9ExecStateE
__ZNK3KJS6JSCell14isGetterSetterEv
__ZNK3KJS6JSCell17getTruncatedInt32ERi
__ZNK3KJS6JSCell18getTruncatedUInt32ERj
__ZNK3KJS6JSCell8isObjectEv
__ZNK3KJS6JSCell8isStringEv
__ZNK3KJS6JSCell9classInfoEv
__ZNK3KJS6JSCell9getNumberEv
__ZNK3KJS6JSCell9getStringERNS_7UStringE
......@@ -296,12 +299,12 @@ __ZNK3KJS7UString8toUInt32EPb
__ZNK3KJS7UString8toUInt32EPbb
__ZNK3KJS8JSObject11hasPropertyEPNS_9ExecStateERKNS_10IdentifierE
__ZNK3KJS8JSObject11hasPropertyEPNS_9ExecStateEj
__ZNK3KJS8JSObject12defaultValueEPNS_9ExecStateENS_6JSTypeE
__ZNK3KJS8JSObject12defaultValueEPNS_9ExecStateENS_7JSValue22PreferredPrimitiveTypeE
__ZNK3KJS8JSObject12toThisObjectEPNS_9ExecStateE
__ZNK3KJS8JSObject14toGlobalObjectEPNS_9ExecStateE
__ZNK3KJS8JSObject21getPropertyAttributesEPNS_9ExecStateERKNS_10IdentifierERj
__ZNK3KJS8JSObject21implementsHasInstanceEv
__ZNK3KJS8JSObject4typeEv
__ZNK3KJS8JSObject8isObjectEv
__ZNK3KJS8JSObject8toNumberEPNS_9ExecStateE
__ZNK3KJS8JSObject8toObjectEPNS_9ExecStateE
__ZNK3KJS8JSObject8toStringEPNS_9ExecStateE
......
......@@ -63,12 +63,7 @@ JSPropertyNameIterator::~JSPropertyNameIterator()
invalidate();
}
JSType JSPropertyNameIterator::type() const
{
return UnspecifiedType;
}
JSValue* JSPropertyNameIterator::toPrimitive(ExecState*, JSType) const
JSValue* JSPropertyNameIterator::toPrimitive(ExecState*, PreferredPrimitiveType) const
{
ASSERT_NOT_REACHED();
return 0;
......
......@@ -42,8 +42,7 @@ namespace KJS {
virtual ~JSPropertyNameIterator();
virtual JSType type() const;
virtual JSValue* toPrimitive(ExecState*, JSType) const;
virtual JSValue* toPrimitive(ExecState*, PreferredPrimitiveType) const;
virtual bool getPrimitiveNumber(ExecState*, double&, JSValue*&);
virtual bool toBoolean(ExecState*) const;
virtual double toNumber(ExecState*) const;
......
......@@ -98,35 +98,41 @@ static int depth(CodeBlock* codeBlock, ScopeChain& sc)
return scopeDepth;
}
static bool fastIsNumber(JSValue* value, double& arg) {
// FIXME: This operation should be called "getNumber", not "isNumber" (as it is in JSValue.h).
// FIXME: There's no need to have a "slow" version of this. All versions should be fast.
static bool fastIsNumber(JSValue* value, double& arg)
{
if (JSImmediate::isNumber(value))
arg = JSImmediate::getTruncatedInt32(value);
else if (Heap::fastIsNumber(static_cast<JSCell*>(value)))
else if (Heap::isNumber(static_cast<JSCell*>(value)))
arg = static_cast<JSNumberCell*>(value)->value();
else
return false;
return true;
}
static bool fastToInt32(JSValue* value, int32_t& arg) {
// FIXME: Why doesn't JSValue::toInt32 have the Heap::isNumber optimization?
static bool fastToInt32(JSValue* value, int32_t& arg)
{
if (JSImmediate::isNumber(value))
arg = JSImmediate::getTruncatedInt32(value);
else if (Heap::fastIsNumber(static_cast<JSCell*>(value)))
arg = static_cast<JSNumberCell*>(value)->fastToInt32();
else if (Heap::isNumber(static_cast<JSCell*>(value)))
arg = static_cast<JSNumberCell*>(value)->toInt32();
else
return false;
return true;
}
static ALWAYS_INLINE bool fastToUInt32(JSValue* value, uint32_t& arg) {
static ALWAYS_INLINE bool fastToUInt32(JSValue* value, uint32_t& arg)
{
if (JSImmediate::isNumber(value)) {
if (JSImmediate::getTruncatedUInt32(value, arg))
return true;
bool scratch;
arg = JSValue::toUInt32SlowCase(JSImmediate::getTruncatedInt32(value), scratch);
return true;
} else if (Heap::fastIsNumber(static_cast<JSCell*>(value)))
arg = static_cast<JSNumberCell*>(value)->fastToUInt32();
} else if (Heap::isNumber(static_cast<JSCell*>(value)))
arg = static_cast<JSNumberCell*>(value)->toUInt32();
else
return false;
return true;
......@@ -177,8 +183,8 @@ static inline bool jsLessEq(ExecState* exec, JSValue* v1, JSValue* v2)
static JSValue* jsAddSlowCase(ExecState* exec, JSValue* v1, JSValue* v2)
{
// exception for the Date exception in defaultValue()
JSValue* p1 = v1->toPrimitive(exec, UnspecifiedType);
JSValue* p2 = v2->toPrimitive(exec, UnspecifiedType);
JSValue* p1 = v1->toPrimitive(exec);
JSValue* p2 = v2->toPrimitive(exec);
if (p1->isString() || p2->isString()) {
UString value = p1->toString(exec) + p2->toString(exec);
......@@ -203,15 +209,10 @@ static inline JSValue* jsAdd(ExecState* exec, JSValue* v1, JSValue* v2)
{
double left;
double right;
if (fastIsNumber(v1, left) && fastIsNumber(v2, right))
return jsNumber(exec, left + right);
JSType t1 = v1->type();
JSType t2 = v2->type();
const unsigned bothTypes = (t1 << 3) | t2;
ASSERT(bothTypes != ((NumberType << 3) | NumberType));
if (bothTypes == ((StringType << 3) | StringType)) {
if (v1->isString() && v2->isString()) {
UString value = static_cast<JSString*>(v1)->value() + static_cast<JSString*>(v2)->value();
if (value.isNull())
return throwOutOfMemoryError(exec);
......@@ -224,30 +225,24 @@ static inline JSValue* jsAdd(ExecState* exec, JSValue* v1, JSValue* v2)
static JSValue* jsTypeStringForValue(ExecState* exec, JSValue* v)
{
switch (v->type()) {
case UndefinedType:
if (v->isUndefined())
return jsString(exec, "undefined");
if (v->isBoolean())
return jsString(exec, "boolean");
if (v->isNumber())
return jsString(exec, "number");
if (v->isString())
return jsString(exec, "string");
if (v->isObject()) {
// Return "undefined" for objects that should be treated
// as null when doing comparisons.
if (static_cast<JSObject*>(v)->masqueradeAsUndefined())
return jsString(exec, "undefined");
case NullType:
return jsString(exec, "object");
case BooleanType:
return jsString(exec, "boolean");
case NumberType:
return jsString(exec, "number");
case StringType:
return jsString(exec, "string");
default:
if (v->isObject()) {
// Return "undefined" for objects that should be treated
// as null when doing comparisons.
if (static_cast<JSObject*>(v)->masqueradeAsUndefined())
return jsString(exec, "undefined");
CallData callData;
if (static_cast<JSObject*>(v)->getCallData(callData) != CallTypeNone)
return jsString(exec, "function");
}
return jsString(exec, "object");
CallData callData;
if (static_cast<JSObject*>(v)->getCallData(callData) != CallTypeNone)
return jsString(exec, "function");
}
return jsString(exec, "object");
}
static bool NEVER_INLINE resolve(ExecState* exec, Instruction* vPC, Register* r, ScopeChainNode* scopeChain, CodeBlock* codeBlock, JSValue*& exceptionValue)
......@@ -1553,7 +1548,7 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, ExecState* exec, RegisterFi
int32_t left;
uint32_t right;
if (JSImmediate::areBothImmediateNumbers(val, shift))
r[dst] = jsNumber(exec, JSImmediate::getTruncatedInt32(val) << (JSImmediate::toTruncatedUInt32(shift) & 0x1f));
r[dst] = jsNumber(exec, JSImmediate::getTruncatedInt32(val) << (JSImmediate::getTruncatedUInt32(shift) & 0x1f));
else if (fastToInt32(val, left) && fastToUInt32(shift, right))
r[dst] = jsNumber(exec, left << (right & 0x1f));
else {
......@@ -2271,7 +2266,7 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, ExecState* exec, RegisterFi
int tableIndex = (++vPC)->u.operand;
int defaultOffset = (++vPC)->u.operand;
JSValue* scrutinee = r[(++vPC)->u.operand].jsValue(exec);
if (scrutinee->type() != StringType)
if (!scrutinee->isString())
vPC += defaultOffset;
else {
UString::Rep* value = static_cast<JSString*>(scrutinee)->value().rep();
......@@ -2294,7 +2289,7 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, ExecState* exec, RegisterFi
int tableIndex = (++vPC)->u.operand;
int defaultOffset = (++vPC)->u.operand;
JSValue* scrutinee = r[(++vPC)->u.operand].jsValue(exec);
if (scrutinee->type() != StringType)
if (!scrutinee->isString())
vPC += defaultOffset;
else
vPC += offsetForStringSwitch(codeBlock->stringSwitchJumpTables[tableIndex], scrutinee, defaultOffset);
......
......@@ -38,7 +38,7 @@ void GetterSetter::mark()
m_setter->mark();
}
JSValue* GetterSetter::toPrimitive(ExecState*, JSType) const
JSValue* GetterSetter::toPrimitive(ExecState*, PreferredPrimitiveType) const
{
ASSERT_NOT_REACHED();
return jsNull();
......@@ -76,4 +76,9 @@ JSObject* GetterSetter::toObject(ExecState* exec) const
return jsNull()->toObject(exec);
}
bool GetterSetter::isGetterSetter() const
{
return true;
}
} // namespace KJS
......@@ -39,8 +39,6 @@ namespace KJS {
{
}
JSType type() const { return GetterSetterType; }
virtual void mark();
JSObject* getter() const { return m_getter; }
......@@ -49,7 +47,9 @@ namespace KJS {
void setSetter(JSObject* setter) { m_setter = setter; }
private:
virtual JSValue* toPrimitive(ExecState*, JSType preferred) const;
virtual bool isGetterSetter() const;
virtual JSValue* toPrimitive(ExecState*, PreferredPrimitiveType) const;
virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue*& value);
virtual bool toBoolean(ExecState*) const;
virtual double toNumber(ExecState*) const;
......
......@@ -215,4 +215,19 @@ JSValue* JSCell::getJSNumber()
return 0;
}
bool JSCell::isString() const
{
return false;
}
bool JSCell::isGetterSetter() const
{
return false;
}
bool JSCell::isObject() const
{
return false;
}
} // namespace KJS
......@@ -43,11 +43,11 @@ namespace KJS {
public:
// Querying the type.
virtual JSType type() const = 0;
bool isNumber() const;
bool isString() const;
bool isObject() const;
bool isObject(const ClassInfo*) const; // FIXME: Merge with inherits.
virtual bool isString() const;
virtual bool isGetterSetter() const;
virtual bool isObject() const;
virtual bool isObject(const ClassInfo*) const;
// Extracting the value.
bool getNumber(double&) const;
......@@ -66,7 +66,7 @@ namespace KJS {
virtual bool getTruncatedUInt32(uint32_t&) const;
// Basic conversions.
virtual JSValue* toPrimitive(ExecState*, JSType preferredType = UnspecifiedType) const = 0;
virtual JSValue* toPrimitive(ExecState*, PreferredPrimitiveType) const = 0;
virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue*&) = 0;
virtual bool toBoolean(ExecState*) const = 0;
virtual double toNumber(ExecState*) const = 0;
......@@ -110,17 +110,7 @@ namespace KJS {
inline bool JSCell::isNumber() const
{
return type() == NumberType;
}
inline bool JSCell::isString() const
{
return type() == StringType;
}
inline bool JSCell::isObject() const
{
return type() == ObjectType;
return Heap::isNumber(const_cast<JSCell*>(this));
}
inline bool JSCell::marked() const
......@@ -158,6 +148,11 @@ namespace KJS {
return !JSImmediate::isImmediate(this) && asCell()->isString();
}
inline bool JSValue::isGetterSetter() const
{
return !JSImmediate::isImmediate(this) && asCell()->isGetterSetter();
}
inline bool JSValue::isObject() const
{
return !JSImmediate::isImmediate(this) && asCell()->isObject();
......@@ -233,12 +228,7 @@ namespace KJS {
return JSImmediate::isImmediate(this) || asCell()->marked();
}
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, PreferredPrimitiveType preferredType) const
{
return JSImmediate::isImmediate(this) ? const_cast<JSValue*>(this) : asCell()->toPrimitive(exec, preferredType);
}
......
/*
* Copyright (C) 2003, 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
* Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
* Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org)
*
* This library is free software; you can redistribute it and/or
......@@ -22,7 +22,6 @@
#ifndef KJS_JS_IMMEDIATE_H
#define KJS_JS_IMMEDIATE_H
#include "JSType.h"
#include <wtf/Assertions.h>
#include <wtf/AlwaysInline.h>
#include <wtf/MathExtras.h>
......@@ -40,7 +39,7 @@ namespace KJS {
class UString;
/*
* A JSValue* is either a pointer to a cell (a heap-allocated object) or an immediate (a type-tagged
* A JSValue* is either a pointer to a cell (a heap-allocated object) or an immediate (a type-tagged
* value masquerading as a pointer). The low two bits in a JSValue* are available for type tagging
* because allocator alignment guarantees they will be 00 in cell pointers.
*
......@@ -82,8 +81,9 @@ namespace KJS {
*/
class JSImmediate {
private:
static const uintptr_t TagMask = 0x3u; // primary tag is 2 bits long
static const uintptr_t TagBitTypeInteger = 0x1u; // bottom bit set indicates int, this dominates the following bit
static const uintptr_t TagBitTypeInteger = 0x1u; // bottom bit set indicates integer, this dominates the following bit
static const uintptr_t TagBitTypeOther = 0x2u; // second bit set indicates immediate other than an integer
static const uintptr_t ExtendedTagMask = 0xCu; // extended tag holds a further two bits
......@@ -103,12 +103,12 @@ namespace KJS {
public:
static ALWAYS_INLINE bool isImmediate(const JSValue* v)
{
return (reinterpret_cast<uintptr_t>(v) & TagMask);
return reinterpret_cast<uintptr_t>(v) & TagMask;
}
static ALWAYS_INLINE bool isNumber(const JSValue* v)
{
return (reinterpret_cast<uintptr_t>(v) & TagBitTypeInteger);
return reinterpret_cast<uintptr_t>(v) & TagBitTypeInteger;
}
static ALWAYS_INLINE bool isPositiveNumber(const JSValue* v)
......@@ -119,13 +119,13 @@ namespace KJS {
static ALWAYS_INLINE bool isBoolean(const JSValue* v)
{
return ((reinterpret_cast<uintptr_t>(v) & FullTagTypeMask) == FullTagTypeBool);
return (reinterpret_cast<uintptr_t>(v) & FullTagTypeMask) == FullTagTypeBool;
}
static ALWAYS_INLINE bool isUndefinedOrNull(const JSValue* v)
{
// Undefined and null share the same value, bar the 'undefined' bit in the extended tag.
return ((reinterpret_cast<uintptr_t>(v) & ~ExtendedTagBitUndefined) == FullTagTypeNull);
return (reinterpret_cast<uintptr_t>(v) & ~ExtendedTagBitUndefined) == FullTagTypeNull;
}
static bool isNegative(const JSValue* v)
......@@ -147,9 +147,14 @@ namespace KJS {
static JSValue* from(unsigned long long);
static JSValue* from(double);
static ALWAYS_INLINE bool isEitherImmediate(const JSValue* v1, const JSValue* v2)
{
return (reinterpret_cast<uintptr_t>(v1) | reinterpret_cast<uintptr_t>(v2)) & TagMask;
}
static ALWAYS_INLINE bool areBothImmediateNumbers(const JSValue* v1, const JSValue* v2)
{
return (reinterpret_cast<uintptr_t>(v1) & reinterpret_cast<uintptr_t>(v2) & TagBitTypeInteger);
return reinterpret_cast<uintptr_t>(v1) & reinterpret_cast<uintptr_t>(v2) & TagBitTypeInteger;
}
static ALWAYS_INLINE JSValue* andImmediateNumbers(const JSValue* v1, const JSValue* v2)
......@@ -213,14 +218,13 @@ namespace KJS {
static bool toBoolean(const JSValue*);
static JSObject* toObject(const JSValue*, ExecState*);
static UString toString(const JSValue*);
static uint32_t toTruncatedUInt32(const JSValue*);
static JSType type(const JSValue*);
static bool getUInt32(const JSValue*, uint32_t&);
static bool getTruncatedInt32(const JSValue*, int32_t&);
static bool getTruncatedUInt32(const JSValue*, uint32_t&);
static int32_t getTruncatedInt32(const JSValue*);
static uint32_t getTruncatedUInt32(const JSValue*);
static JSValue* trueImmediate();
static JSValue* falseImmediate();
......@@ -232,7 +236,6 @@ namespace KJS {
static JSObject* prototype(const JSValue*, ExecState*);
private:
// Immediate values are restricted to a 30 bit signed value.
static const int minImmediateInt = ((-INT_MAX) - 1) >> IntegerPayloadShift;
static const int maxImmediateInt = INT_MAX >> IntegerPayloadShift;
static const unsigned maxImmediateUInt = maxImmediateInt;
......@@ -269,7 +272,7 @@ namespace KJS {
static ALWAYS_INLINE bool boolValue(const JSValue* v)
{
return (rawValue(v) & ExtendedPayloadBitBoolValue) != 0;
return rawValue(v) & ExtendedPayloadBitBoolValue;
}
static ALWAYS_INLINE uintptr_t rawValue(const JSValue* v)
......@@ -290,12 +293,12 @@ namespace KJS {
{
ASSERT(isImmediate(v));
uintptr_t bits = rawValue(v);