Changeset 35830 in webkit for trunk/JavaScriptCore/kjs


Ignore:
Timestamp:
Aug 18, 2008, 9:39:04 PM (17 years ago)
Author:
Darin Adler
Message:

JavaScriptCore:

2008-08-12 Darin Adler <Darin Adler>

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.
  • 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 Adler>

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 Adler>

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 Adler>

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 Adler>

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.
Location:
trunk/JavaScriptCore/kjs
Files:
18 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/kjs/GetterSetter.cpp

    r35008 r35830  
    3939}
    4040
    41 JSValue* GetterSetter::toPrimitive(ExecState*, JSType) const
     41JSValue* GetterSetter::toPrimitive(ExecState*, PreferredPrimitiveType) const
    4242{
    4343    ASSERT_NOT_REACHED();
     
    7777}
    7878
     79bool GetterSetter::isGetterSetter() const
     80{
     81    return true;
     82}
     83
    7984} // namespace KJS
  • trunk/JavaScriptCore/kjs/GetterSetter.h

    r35022 r35830  
    4040        }
    4141
    42         JSType type() const { return GetterSetterType; }
    43 
    4442        virtual void mark();
    4543
     
    5048
    5149    private:
    52         virtual JSValue* toPrimitive(ExecState*, JSType preferred) const;
     50        virtual bool isGetterSetter() const;
     51
     52        virtual JSValue* toPrimitive(ExecState*, PreferredPrimitiveType) const;
    5353        virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue*& value);
    5454        virtual bool toBoolean(ExecState*) const;
  • trunk/JavaScriptCore/kjs/JSCell.cpp

    r34921 r35830  
    216216}
    217217
     218bool JSCell::isString() const
     219{
     220    return false;
     221}
     222
     223bool JSCell::isGetterSetter() const
     224{
     225    return false;
     226}
     227
     228bool JSCell::isObject() const
     229{
     230    return false;
     231}
     232
    218233} // namespace KJS
  • trunk/JavaScriptCore/kjs/JSCell.h

    r35807 r35830  
    4444    public:
    4545        // Querying the type.
    46         virtual JSType type() const = 0;
    4746        bool isNumber() const;
    48         bool isString() const;
    49         bool isObject() const;
    50         bool isObject(const ClassInfo*) const; // FIXME: Merge with inherits.
     47        virtual bool isString() const;
     48        virtual bool isGetterSetter() const;
     49        virtual bool isObject() const;
     50        virtual bool isObject(const ClassInfo*) const;
    5151
    5252        // Extracting the value.
     
    6767
    6868        // Basic conversions.
    69         virtual JSValue* toPrimitive(ExecState*, JSType preferredType = UnspecifiedType) const = 0;
     69        virtual JSValue* toPrimitive(ExecState*, PreferredPrimitiveType) const = 0;
    7070        virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue*&) = 0;
    7171        virtual bool toBoolean(ExecState*) const = 0;
     
    111111    inline bool JSCell::isNumber() const
    112112    {
    113         return type() == NumberType;
    114     }
    115 
    116     inline bool JSCell::isString() const
    117     {
    118         return type() == StringType;
    119     }
    120 
    121     inline bool JSCell::isObject() const
    122     {
    123         return type() == ObjectType;
     113        return Heap::isNumber(const_cast<JSCell*>(this));
    124114    }
    125115
     
    157147    {
    158148        return !JSImmediate::isImmediate(this) && asCell()->isString();
     149    }
     150
     151    inline bool JSValue::isGetterSetter() const
     152    {
     153        return !JSImmediate::isImmediate(this) && asCell()->isGetterSetter();
    159154    }
    160155
     
    234229    }
    235230
    236     inline JSType JSValue::type() const
    237     {
    238         return JSImmediate::isImmediate(this) ? JSImmediate::type(this) : asCell()->type();
    239     }
    240 
    241     inline JSValue* JSValue::toPrimitive(ExecState* exec, JSType preferredType) const
     231    inline JSValue* JSValue::toPrimitive(ExecState* exec, PreferredPrimitiveType preferredType) const
    242232    {
    243233        return JSImmediate::isImmediate(this) ? const_cast<JSValue*>(this) : asCell()->toPrimitive(exec, preferredType);
  • trunk/JavaScriptCore/kjs/JSImmediate.h

    r35782 r35830  
    11/*
    2  *  Copyright (C) 2003, 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
     2 *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
    33 *  Copyright (C) 2006 Alexey Proskuryakov ([email protected])
    44 *
     
    2323#define KJS_JS_IMMEDIATE_H
    2424
    25 #include "JSType.h"
    2625#include <wtf/Assertions.h>
    2726#include <wtf/AlwaysInline.h>
     
    4140
    4241    /*
    43      * A JSValue*  is either a pointer to a cell (a heap-allocated object) or an immediate (a type-tagged
     42     * A JSValue* is either a pointer to a cell (a heap-allocated object) or an immediate (a type-tagged
    4443     * value masquerading as a pointer). The low two bits in a JSValue* are available for type tagging
    4544     * because allocator alignment guarantees they will be 00 in cell pointers.
     
    8382
    8483    class JSImmediate {
     84    private:
    8585        static const uintptr_t TagMask           = 0x3u; // primary tag is 2 bits long
    86         static const uintptr_t TagBitTypeInteger = 0x1u; // bottom bit set indicates int, this dominates the following bit
     86        static const uintptr_t TagBitTypeInteger = 0x1u; // bottom bit set indicates integer, this dominates the following bit
    8787        static const uintptr_t TagBitTypeOther   = 0x2u; // second bit set indicates immediate other than an integer
    8888
     
    104104        static ALWAYS_INLINE bool isImmediate(const JSValue* v)
    105105        {
    106             return (reinterpret_cast<uintptr_t>(v) & TagMask);
     106            return reinterpret_cast<uintptr_t>(v) & TagMask;
    107107        }
    108108       
    109109        static ALWAYS_INLINE bool isNumber(const JSValue* v)
    110110        {
    111             return (reinterpret_cast<uintptr_t>(v) & TagBitTypeInteger);
     111            return reinterpret_cast<uintptr_t>(v) & TagBitTypeInteger;
    112112        }
    113113
     
    120120        static ALWAYS_INLINE bool isBoolean(const JSValue* v)
    121121        {
    122             return ((reinterpret_cast<uintptr_t>(v) & FullTagTypeMask) == FullTagTypeBool);
     122            return (reinterpret_cast<uintptr_t>(v) & FullTagTypeMask) == FullTagTypeBool;
    123123        }
    124124       
     
    126126        {
    127127            // Undefined and null share the same value, bar the 'undefined' bit in the extended tag.
    128             return ((reinterpret_cast<uintptr_t>(v) & ~ExtendedTagBitUndefined) == FullTagTypeNull);
     128            return (reinterpret_cast<uintptr_t>(v) & ~ExtendedTagBitUndefined) == FullTagTypeNull;
    129129        }
    130130
     
    148148        static JSValue* from(double);
    149149
     150        static ALWAYS_INLINE bool isEitherImmediate(const JSValue* v1, const JSValue* v2)
     151        {
     152            return (reinterpret_cast<uintptr_t>(v1) | reinterpret_cast<uintptr_t>(v2)) & TagMask;
     153        }
     154
    150155        static ALWAYS_INLINE bool areBothImmediateNumbers(const JSValue* v1, const JSValue* v2)
    151156        {
    152              return (reinterpret_cast<uintptr_t>(v1) & reinterpret_cast<uintptr_t>(v2) & TagBitTypeInteger);
     157            return reinterpret_cast<uintptr_t>(v1) & reinterpret_cast<uintptr_t>(v2) & TagBitTypeInteger;
    153158        }
    154159
     
    214219        static JSObject* toObject(const JSValue*, ExecState*);
    215220        static UString toString(const JSValue*);
    216         static uint32_t toTruncatedUInt32(const JSValue*);
    217         static JSType type(const JSValue*);
    218221
    219222        static bool getUInt32(const JSValue*, uint32_t&);
     
    222225
    223226        static int32_t getTruncatedInt32(const JSValue*);
     227        static uint32_t getTruncatedUInt32(const JSValue*);
    224228
    225229        static JSValue* trueImmediate();
     
    233237
    234238    private:
    235         // Immediate values are restricted to a 30 bit signed value.
    236239        static const int minImmediateInt = ((-INT_MAX) - 1) >> IntegerPayloadShift;
    237240        static const int maxImmediateInt = INT_MAX >> IntegerPayloadShift;
     
    270273        static ALWAYS_INLINE bool boolValue(const JSValue* v)
    271274        {
    272             return (rawValue(v) & ExtendedPayloadBitBoolValue) != 0;
     275            return rawValue(v) & ExtendedPayloadBitBoolValue;
    273276        }
    274277       
     
    291294        ASSERT(isImmediate(v));
    292295        uintptr_t bits = rawValue(v);
    293         return
    294             (bits & TagBitTypeInteger) ? (bits != TagBitTypeInteger) : // !0 ints
    295             (bits == (FullTagTypeBool | ExtendedPayloadBitBoolValue)); // bool true
    296     }
    297 
    298     ALWAYS_INLINE uint32_t JSImmediate::toTruncatedUInt32(const JSValue* v)
     296        return (bits & TagBitTypeInteger)
     297            ? bits != TagBitTypeInteger // !0 ints
     298            : bits == (FullTagTypeBool | ExtendedPayloadBitBoolValue); // bool true
     299    }
     300
     301    ALWAYS_INLINE uint32_t JSImmediate::getTruncatedUInt32(const JSValue* v)
    299302    {
    300303        ASSERT(isNumber(v));
     
    377380
    378381        // Check for data loss from conversion to int.
    379         if ((intVal != d) || (!intVal && signbit(d)))
     382        if (intVal != d || (!intVal && signbit(d)))
    380383            return 0;
    381384
     
    418421    }
    419422
    420     ALWAYS_INLINE JSType JSImmediate::type(const JSValue* v)
    421     {
    422         ASSERT(isImmediate(v));
    423        
    424         if (isNumber(v))
    425             return NumberType;
    426         if (isBoolean(v))
    427             return BooleanType;
    428         if (v != undefinedImmediate())
    429             return NullType;
    430         return UndefinedType;
    431     }
    432 
    433423    ALWAYS_INLINE JSValue* jsUndefined()
    434424    {
  • trunk/JavaScriptCore/kjs/JSNotAnObject.cpp

    r35807 r35830  
    3838
    3939// JSValue methods
    40 JSValue* JSNotAnObject::toPrimitive(ExecState* exec, JSType) const
     40JSValue* JSNotAnObject::toPrimitive(ExecState* exec, PreferredPrimitiveType) const
    4141{
    4242    UNUSED_PARAM(exec);
  • trunk/JavaScriptCore/kjs/JSNotAnObject.h

    r35245 r35830  
    5858     private:
    5959        // JSValue methods
    60         virtual JSValue* toPrimitive(ExecState*, JSType preferredType = UnspecifiedType) const;
     60        virtual JSValue* toPrimitive(ExecState*, PreferredPrimitiveType) const;
    6161        virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue*&);
    6262        virtual bool toBoolean(ExecState*) const;
  • trunk/JavaScriptCore/kjs/JSNumberCell.cpp

    r35027 r35830  
    2424#include "JSNumberCell.h"
    2525
    26 #include "JSType.h"
    2726#include "NumberObject.h"
    2827#include "ustring.h"
     
    3029namespace KJS {
    3130
    32 JSType JSNumberCell::type() const
    33 {
    34     return NumberType;
    35 }
    36 
    37 JSValue* JSNumberCell::toPrimitive(ExecState*, JSType) const
     31JSValue* JSNumberCell::toPrimitive(ExecState*, PreferredPrimitiveType) const
    3832{
    3933    return const_cast<JSNumberCell*>(this);
  • trunk/JavaScriptCore/kjs/JSNumberCell.h

    r35639 r35830  
    4747        double value() const { return m_value; }
    4848
    49         virtual JSType type() const;
    50 
    51         virtual JSValue* toPrimitive(ExecState*, JSType preferred = UnspecifiedType) const;
     49        virtual JSValue* toPrimitive(ExecState*, PreferredPrimitiveType) const;
    5250        virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue*& value);
    5351        virtual bool toBoolean(ExecState*) const;
     
    5957        virtual JSObject* toThisObject(ExecState*) const;
    6058        virtual JSValue* getJSNumber();
    61         int32_t fastToInt32() const;
    62         uint32_t fastToUInt32() const;
     59
     60        int32_t toInt32() const;
     61        uint32_t toUInt32() const;
    6362
    6463        void* operator new(size_t size, ExecState* exec)
     
    149148    }
    150149
    151     inline int32_t JSNumberCell::fastToInt32() const
     150    inline int32_t JSNumberCell::toInt32() const
    152151    {
    153152        if (m_value >= -2147483648.0 && m_value < 2147483648.0)
     
    157156    }
    158157
    159     inline uint32_t JSNumberCell::fastToUInt32() const
     158    inline uint32_t JSNumberCell::toUInt32() const
    160159    {
    161160        if (m_value >= 0.0 && m_value < 4294967296.0)
  • trunk/JavaScriptCore/kjs/JSObject.cpp

    r35807 r35830  
    6868}
    6969
    70 JSType JSObject::type() const
    71 {
    72     return ObjectType;
    73 }
    74 
    7570UString JSObject::className() const
    7671{
     
    235230
    236231    JSValue* result = call(exec, function, callType, callData, const_cast<JSObject*>(object), exec->emptyList());
    237     ASSERT(result->type() != GetterSetterType);
     232    ASSERT(!result->isGetterSetter());
    238233    if (exec->hadException())
    239234        return exec->exception();
     
    245240bool JSObject::getPrimitiveNumber(ExecState* exec, double& number, JSValue*& result)
    246241{
    247     result = defaultValue(exec, NumberType);
     242    result = defaultValue(exec, PreferNumber);
    248243    number = result->toNumber(exec);
    249244    return !result->isString();
     
    251246
    252247// ECMA 8.6.2.6
    253 JSValue* JSObject::defaultValue(ExecState* exec, JSType hint) const
     248JSValue* JSObject::defaultValue(ExecState* exec, PreferredPrimitiveType hint) const
    254249{
    255250    // Must call toString first for Date objects.
    256     if ((hint == StringType) || (hint != NumberType && m_prototype == exec->lexicalGlobalObject()->datePrototype())) {
     251    if ((hint == PreferString) || (hint != PreferNumber && m_prototype == exec->lexicalGlobalObject()->datePrototype())) {
    257252        if (JSValue* value = callDefaultValueFunction(exec, this, exec->propertyNames().toString))
    258253            return value;
     
    286281    JSValue* object = getDirect(propertyName);
    287282    GetterSetter* getterSetter;
    288     if (object && object->type() == GetterSetterType)
     283    if (object && object->isGetterSetter())
    289284        getterSetter = static_cast<GetterSetter*>(object);
    290285    else {
     
    301296    JSValue* object = getDirect(propertyName);
    302297    GetterSetter* getterSetter;
    303     if (object && object->type() == GetterSetterType)
     298    if (object && object->isGetterSetter())
    304299        getterSetter = static_cast<GetterSetter*>(object);
    305300    else {
     
    318313        JSValue* value = object->getDirect(propertyName);
    319314        if (value) {
    320             if (value->type() != GetterSetterType)
     315            if (!value->isGetterSetter())
    321316                return jsUndefined();
    322317            JSObject* functionObject = static_cast<GetterSetter*>(value)->getter();
     
    338333        JSValue* value = object->getDirect(propertyName);
    339334        if (value) {
    340             if (value->type() != GetterSetterType)
     335            if (!value->isGetterSetter())
    341336                return jsUndefined();
    342337            JSObject* functionObject = static_cast<GetterSetter*>(value)->setter();
     
    429424double JSObject::toNumber(ExecState* exec) const
    430425{
    431     JSValue* primitive = toPrimitive(exec, NumberType);
     426    JSValue* primitive = toPrimitive(exec, PreferNumber);
    432427    if (exec->hadException()) // should be picked up soon in nodes.cpp
    433428        return 0.0;
     
    437432UString JSObject::toString(ExecState* exec) const
    438433{
    439     JSValue* primitive = toPrimitive(exec, StringType);
     434    JSValue* primitive = toPrimitive(exec, PreferString);
    440435    if (exec->hadException())
    441436        return "";
     
    476471}
    477472
     473bool JSObject::isObject() const
     474{
     475    return true;
     476}
     477
    478478JSObject* constructEmptyObject(ExecState* exec)
    479479{
  • trunk/JavaScriptCore/kjs/JSObject.h

    r35807 r35830  
    2929#include "ExecState.h"
    3030#include "JSNumberCell.h"
    31 #include "JSType.h"
    3231#include "PropertyMap.h"
    3332#include "PropertySlot.h"
     
    6867
    6968        virtual void mark();
    70         virtual JSType type() const;
    71 
    72         bool inherits(const ClassInfo* classInfo) const { return isObject(classInfo); } // FIXME: Merge with isObject.
     69
     70        bool inherits(const ClassInfo* classInfo) const { return JSCell::isObject(classInfo); }
    7371
    7472        JSValue* prototype() const;
     
    10199        virtual bool deleteProperty(ExecState*, unsigned propertyName);
    102100
    103         virtual JSValue* defaultValue(ExecState*, JSType hint) const;
     101        virtual JSValue* defaultValue(ExecState*, PreferredPrimitiveType) const;
    104102
    105103        virtual bool implementsHasInstance() const;
     
    108106        virtual void getPropertyNames(ExecState*, PropertyNameArray&);
    109107
    110         virtual JSValue* toPrimitive(ExecState*, JSType preferredType = UnspecifiedType) const;
     108        virtual JSValue* toPrimitive(ExecState*, PreferredPrimitiveType = NoPreference) const;
    111109        virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue*& value);
    112110        virtual bool toBoolean(ExecState*) const;
     
    155153
    156154    private:
     155        virtual bool isObject() const;
     156
    157157        const HashEntry* findPropertyHashEntry(ExecState*, const Identifier& propertyName) const;
    158158        JSValue* m_prototype;
     
    258258{
    259259    if (JSValue** location = getDirectLocation(propertyName, slotIsWriteable)) {
    260         if (m_propertyMap.hasGetterSetterProperties() && location[0]->type() == GetterSetterType) {
     260        if (m_propertyMap.hasGetterSetterProperties() && location[0]->isGetterSetter()) {
    261261            slotIsWriteable = false;
    262262            fillGetterPropertySlot(slot, location);
     
    282282{
    283283    if (JSValue** location = getDirectLocation(propertyName)) {
    284         if (m_propertyMap.hasGetterSetterProperties() && location[0]->type() == GetterSetterType)
     284        if (m_propertyMap.hasGetterSetterProperties() && location[0]->isGetterSetter())
    285285            fillGetterPropertySlot(slot, location);
    286286        else
     
    310310}
    311311
    312 inline JSValue* JSObject::toPrimitive(ExecState* exec, JSType preferredType) const
     312inline JSValue* JSObject::toPrimitive(ExecState* exec, PreferredPrimitiveType preferredType) const
    313313{
    314314    return defaultValue(exec, preferredType);
  • trunk/JavaScriptCore/kjs/JSString.cpp

    r35806 r35830  
    3131namespace KJS {
    3232
    33 JSValue* JSString::toPrimitive(ExecState*, JSType) const
     33JSValue* JSString::toPrimitive(ExecState*, PreferredPrimitiveType) const
    3434{
    3535    return const_cast<JSString*>(this);
     
    110110}
    111111
     112bool JSString::isString() const
     113{
     114    // FIXME: Change JSCell::isString to a non-virtual implementation like the one in Machine::isJSString.
     115    return true;
     116}
     117
    112118JSString* jsString(ExecState* exec, const char* s)
    113119{
  • trunk/JavaScriptCore/kjs/JSString.h

    r35806 r35830  
    6262
    6363    private:
    64         virtual JSType type() const { return StringType; }
     64        virtual bool isString() const;
    6565
    66         virtual JSValue* toPrimitive(ExecState*, JSType preferred = UnspecifiedType) const;
     66        virtual JSValue* toPrimitive(ExecState*, PreferredPrimitiveType) const;
    6767        virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue*& value);
    6868        virtual bool toBoolean(ExecState*) const;
  • trunk/JavaScriptCore/kjs/JSValue.h

    r35203 r35830  
    5959    public:
    6060        // Querying the type.
    61         JSType type() const;
    6261        bool isUndefined() const;
    6362        bool isNull() const;
     
    6665        bool isNumber() const;
    6766        bool isString() const;
     67        bool isGetterSetter() const;
    6868        bool isObject() const;
    6969        bool isObject(const ClassInfo*) const; // FIXME: Merge with inherits.
     
    8989       
    9090        // Basic conversions.
    91         JSValue* toPrimitive(ExecState*, JSType preferredType = UnspecifiedType) const;
     91        enum PreferredPrimitiveType { NoPreference, PreferNumber, PreferString };
     92        JSValue* toPrimitive(ExecState*, PreferredPrimitiveType = NoPreference) const;
    9293        bool getPrimitiveNumber(ExecState*, double& number, JSValue*&);
    9394
     
    188189    inline bool JSValue::getBoolean() const
    189190    {
    190         return JSImmediate::isBoolean(this) ? JSImmediate::toBoolean(this) : false;
     191        return this == jsBoolean(true);
    191192    }
    192193
  • trunk/JavaScriptCore/kjs/collector.cpp

    r35663 r35830  
    10241024static const char* typeName(JSCell* val)
    10251025{
    1026     const char* name = "???";
    1027     switch (val->type()) {
    1028         case UnspecifiedType:
    1029             break;
    1030         case UndefinedType:
    1031             name = "undefined";
    1032             break;
    1033         case NullType:
    1034             name = "null";
    1035             break;
    1036         case BooleanType:
    1037             name = "boolean";
    1038             break;
    1039         case StringType:
    1040             name = "string";
    1041             break;
    1042         case NumberType:
    1043             name = "number";
    1044             break;
    1045         case ObjectType: {
    1046             const ClassInfo* info = static_cast<JSObject*>(val)->classInfo();
    1047             name = info ? info->className : "Object";
    1048             break;
    1049         }
    1050         case GetterSetterType:
    1051             name = "gettersetter";
    1052             break;
    1053     }
    1054     return name;
     1026    if (val->isString())
     1027        return "string";
     1028    if (val->isNumber())
     1029        return "number";
     1030    if (val->isGetterSetter())
     1031        return "gettersetter";
     1032    ASSERT(val->isObject());
     1033    const ClassInfo* info = static_cast<JSObject*>(val)->classInfo();
     1034    return info ? info->className : "Object";
    10551035}
    10561036
  • trunk/JavaScriptCore/kjs/collector.h

    r35807 r35830  
    108108
    109109        JSGlobalData* globalData() const { return m_globalData; }
    110         static bool fastIsNumber(JSCell*);
     110        static bool isNumber(JSCell*);
     111
    111112    private:
    112113        template <Heap::HeapType heapType> void* heapAllocate(size_t);
     
    218219    };
    219220   
    220     inline bool Heap::fastIsNumber(JSCell* cell)
     221    inline bool Heap::isNumber(JSCell* cell)
    221222    {
    222223        CollectorBlock* block = Heap::cellBlock(cell);
  • trunk/JavaScriptCore/kjs/nodes.h

    r35813 r35830  
    2929#include "Error.h"
    3030#include "JSString.h"
     31#include "JSType.h"
    3132#include "LabelStack.h"
    3233#include "Opcode.h"
  • trunk/JavaScriptCore/kjs/operations.cpp

    r35027 r35830  
    3737
    3838// ECMA 11.9.3
    39 bool equal(ExecState *exec, JSValue *v1, JSValue *v2)
     39bool equal(ExecState* exec, JSValue* v1, JSValue* v2)
    4040{
    41     JSType t1 = v1->type();
    42     JSType t2 = v2->type();
    43    
    44     if (t1 != t2) {
    45         if (t1 == UndefinedType)
    46             t1 = NullType;
    47         if (t2 == UndefinedType)
    48             t2 = NullType;
    49        
    50         if (t1 == BooleanType)
    51             t1 = NumberType;
    52         if (t2 == BooleanType)
    53             t2 = NumberType;
    54        
    55         if (t1 == NumberType && t2 == StringType) {
    56             // use toNumber
    57         } else if (t1 == StringType && t2 == NumberType)
    58             t1 = NumberType;
    59             // use toNumber
    60         else {
    61             if ((t1 == StringType || t1 == NumberType) && t2 == ObjectType) {
    62                 v2 = v2->toPrimitive(exec);
    63                 if (exec->hadException())
    64                     return false;
    65                 return equal(exec, v1, v2);
    66             }
    67             if (t1 == NullType && t2 == ObjectType)
    68                 return static_cast<JSObject *>(v2)->masqueradeAsUndefined();
    69             if (t1 == ObjectType && (t2 == StringType || t2 == NumberType)) {
    70                 v1 = v1->toPrimitive(exec);
    71                 if (exec->hadException())
    72                     return false;
    73                 return equal(exec, v1, v2);
    74             }
    75             if (t1 == ObjectType && t2 == NullType)
    76                 return static_cast<JSObject *>(v1)->masqueradeAsUndefined();
    77             if (t1 != t2)
    78                 return false;
    79         }
     41startOver:
     42    if (JSImmediate::areBothImmediateNumbers(v1, v2))
     43        return v1 == v2;
     44
     45    if (v1->isNumber() && v2->isNumber())
     46        return v1->uncheckedGetNumber() == v2->uncheckedGetNumber();
     47
     48    bool s1 = v1->isString();
     49    bool s2 = v2->isString();
     50    if (s1 && s2)
     51        return static_cast<JSString*>(v1)->value() == static_cast<JSString*>(v2)->value();
     52
     53    if (v1->isUndefinedOrNull()) {
     54        if (v2->isUndefinedOrNull())
     55            return true;
     56        if (!v2->isObject())
     57            return false;
     58        return static_cast<JSObject*>(v2)->masqueradeAsUndefined();
    8059    }
    81    
    82     if (t1 == UndefinedType || t1 == NullType)
    83         return true;
    84    
    85     if (t1 == NumberType) {
     60
     61    if (v2->isUndefinedOrNull()) {
     62        if (!v1->isObject())
     63            return false;
     64        return static_cast<JSObject*>(v1)->masqueradeAsUndefined();
     65    }
     66
     67    if (v1->isObject()) {
     68        if (v2->isObject())
     69            return v1 == v2;
     70        JSValue* p1 = v1->toPrimitive(exec);
     71        if (exec->hadException())
     72            return false;
     73        v1 = p1;
     74        goto startOver;
     75    }
     76
     77    if (v2->isObject()) {
     78        JSValue* p2 = v2->toPrimitive(exec);
     79        if (exec->hadException())
     80            return false;
     81        v2 = p2;
     82        goto startOver;
     83    }
     84
     85    if (s1 || s2) {
    8686        double d1 = v1->toNumber(exec);
    8787        double d2 = v2->toNumber(exec);
    8888        return d1 == d2;
    8989    }
    90    
    91     if (t1 == StringType)
    92         return static_cast<JSString*>(v1)->value() == static_cast<JSString*>(v2)->value();
    93    
    94     if (t1 == BooleanType)
    95         return v1->toBoolean(exec) == v2->toBoolean(exec);
    96    
    97     // types are Object
     90
     91    if (v1->isBoolean()) {
     92        if (v2->isNumber())
     93            return v1->getBoolean() == v2->uncheckedGetNumber();
     94    } else if (v2->isBoolean()) {
     95        if (v1->isNumber())
     96            return v1->uncheckedGetNumber() == v2->getBoolean();
     97    }
     98
    9899    return v1 == v2;
    99100}
     
    101102bool strictEqual(JSValue* v1, JSValue* v2)
    102103{
    103     JSType t1 = v1->type();
    104     JSType t2 = v2->type();
    105    
    106     if (t1 != t2)
    107         return false;
     104    if (JSImmediate::isEitherImmediate(v1, v2)) {
     105        if (v1 == v2)
     106            return true;
    108107
    109     if (t1 == NumberType)
    110         return v1->getNumber() == v2->getNumber();
    111    
    112     if (t1 == StringType)
    113         return static_cast<JSString*>(v1)->value() == static_cast<JSString*>(v2)->value();
    114    
    115     return v1 == v2; // covers object, boolean, null, and undefined types
     108        // The reason we can't just return false here is that 0 === -0,
     109        // and while the former is an immediate number, the latter is not.
     110        if (v1 == JSImmediate::from(0))
     111            return !JSImmediate::isImmediate(v2)
     112                && static_cast<JSCell*>(v2)->isNumber()
     113                && static_cast<JSNumberCell*>(v2)->value() == 0;
     114        return v2 == JSImmediate::from(0)
     115            && !JSImmediate::isImmediate(v1)
     116            && static_cast<JSCell*>(v1)->isNumber()
     117            && static_cast<JSNumberCell*>(v1)->value() == 0;
     118    }
     119
     120    if (static_cast<JSCell*>(v1)->isNumber())
     121        return static_cast<JSCell*>(v2)->isNumber()
     122            && static_cast<JSNumberCell*>(v1)->value() == static_cast<JSNumberCell*>(v2)->value();
     123
     124    if (static_cast<JSCell*>(v1)->isString())
     125        return static_cast<JSCell*>(v2)->isString()
     126            && static_cast<JSString*>(v1)->value() == static_cast<JSString*>(v2)->value();
     127
     128    return v1 == v2;
    116129}
    117130
Note: See TracChangeset for help on using the changeset viewer.