Changeset 12728 in webkit for trunk/JavaScriptCore/kjs/value.h


Ignore:
Timestamp:
Feb 9, 2006, 10:42:01 PM (19 years ago)
Author:
ggaren
Message:

Reviewed by mjs.

  • Fixed <rdar://problem/4343730> Should switch ConstantValues (null, undefined, true, false) from JS objects to immediate values similar to SimpleNumber

2.0% performance gain on my new super-accurate version of JS iBench.
(I promise to land a version of it soon.)

The gist of the change:
(1) The SimpleNumber class (simple_number.h) is now the JSImmediate
class (JSImmediate.h/.cpp), and it handles not only numbers but also
null, undefined, true, and false.
(2) JSImmediate provides convenience methods for the bit masking
necessary to encode and decode immediate values.
(3) ConstantValues, BooleanImp, NullImp, and UndefinedImp are gone.
(4) JSCell no longer implements functions like getBoolean, because
only a JSImmediate can be a boolean.
(5) JSImmediate no longer uses ALWAYS_INLINE because there's no need,
and ALWAYS_INLINE is a non-portable option of last resort.
(6) Type is now JSType, and it resides in its own file, JSType.h.
Since I was there, I did some header include sorting as part of this
change.

The rest pretty much explains itself.

  • JavaScriptCore.xcodeproj/project.pbxproj: Removed simple_number.h, added JSImmediate.h/.cpp.
  • bindings/c/c_instance.cpp: (KJS::Bindings::CInstance::defaultValue):
  • bindings/c/c_instance.h:
  • bindings/c/c_utility.cpp: (KJS::Bindings::convertValueToNPVariant):
  • bindings/jni/jni_instance.cpp: (JavaInstance::defaultValue):
  • bindings/jni/jni_instance.h:
  • bindings/jni/jni_jsobject.cpp: (JavaJSObject::convertValueToJObject):
  • bindings/objc/WebScriptObject.mm: (+[WebScriptObject _convertValueToObjcValue:originExecutionContext:executionContext:]): Standardized calls to use getXXX instead of hand-rolling JSValue functionality.
  • bindings/objc/objc_instance.h:
  • bindings/objc/objc_instance.mm: (ObjcInstance::getValueOfUndefinedField): (ObjcInstance::defaultValue):
  • bindings/objc/objc_runtime.h:
  • bindings/objc/objc_runtime.mm: (ObjcFallbackObjectImp::type): (ObjcFallbackObjectImp::defaultValue):
  • bindings/runtime.h: (KJS::Bindings::Instance::getValueOfUndefinedField):
  • bindings/runtime_object.cpp: (RuntimeObjectImp::defaultValue):
  • bindings/runtime_object.h:
  • kjs/JSImmediate.h: Added. (KJS::JSImmediate::isImmediate): (KJS::JSImmediate::isNumber): (KJS::JSImmediate::isBoolean): (KJS::JSImmediate::isUndefinedOrNull): (KJS::JSImmediate::fromDouble): (KJS::JSImmediate::toDouble): (KJS::JSImmediate::toBoolean): (KJS::JSImmediate::trueImmediate): (KJS::JSImmediate::falseImmediate): (KJS::JSImmediate::NaNImmediate): (KJS::JSImmediate::undefinedImmediate): (KJS::JSImmediate::nullImmediate): (KJS::JSImmediate::tag): (KJS::JSImmediate::unTag): (KJS::JSImmediate::getTag): (KJS::JSImmediate::): (KJS::JSImmediate::isIEEE): (KJS::JSImmediate::is32bit): (KJS::JSImmediate::is64bit): (KJS::JSImmediate::NanAsBits): (KJS::JSImmediate::zeroAsBits): (KJS::JSImmediate::oneAsBits):
  • kjs/JSLock.cpp: (KJS::JSLock::lock): Removed hack-o-rama to initialize ConstantValues.
  • kjs/JSType.h: Added.
  • kjs/collector.cpp: (KJS::Collector::protect): (KJS::Collector::unprotect): (KJS::Collector::collect):
  • kjs/internal.cpp: (KJS::StringImp::toPrimitive): (KJS::NumberImp::toPrimitive): (KJS::NumberImp::toBoolean): (KJS::GetterSetterImp::toPrimitive):
  • kjs/internal.h: (KJS::StringImp::type): (KJS::NumberImp::type):
  • kjs/object.cpp: (KJS::JSObject::type): (KJS::tryGetAndCallProperty): Replaced "Are you one of the six things I'm looking for?" test with "Are you not the one thing I'm not looking for" test. (KJS::JSObject::defaultValue): (KJS::JSObject::toPrimitive):
  • kjs/object.h: (KJS::GetterSetterImp::type): (KJS::JSValue::isObject):
  • kjs/operations.cpp: (KJS::equal): (KJS::strictEqual): (KJS::add):
  • kjs/reference.cpp: (KJS::Reference::deleteValue):
  • kjs/simple_number.h: Removed.
  • kjs/string_object.cpp: (StringInstance::getOwnPropertySlot): fixed indentation
  • kjs/value.cpp: (KJS::JSValue::toObject): (KJS::jsNumberCell): New function to quarantine a PIC branch -- allows us to inline jsNumber without adding PIC branches to callers.
  • kjs/value.h: (KJS::jsUndefined): (KJS::jsNull): (KJS::jsNaN): (KJS::jsBoolean): (KJS::jsNumber): (KJS::JSValue::downcast): (KJS::JSValue::isUndefinedOrNull): (KJS::JSValue::isBoolean): (KJS::JSValue::isNumber): (KJS::JSValue::isString): (KJS::JSValue::isObject): (KJS::JSValue::getBoolean): (KJS::JSValue::getNumber): (KJS::JSValue::getString): (KJS::JSValue::getObject): (KJS::JSValue::getUInt32): (KJS::JSValue::mark): Replaced !JSImmediate::is() test with assertion, resulting in a slight performance gain. Callers should always check !marked() before calling mark(), so it's impossible to call mark on a JSImmediate. (KJS::JSValue::marked): (KJS::JSValue::type): (KJS::JSValue::toPrimitive): (KJS::JSValue::toBoolean): (KJS::JSValue::toNumber): (KJS::JSValue::toString):
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/kjs/value.h

    r12317 r12728  
    3434#endif
    3535
    36 #include <assert.h>
     36#include "JSImmediate.h"
     37#include "JSType.h"
     38#include "kxmlcore/Assertions.h"
     39#include "ustring.h"
     40
    3741#include <stdlib.h> // for size_t
    38 #include "simple_number.h"
    39 #include "ustring.h"
    4042
    4143namespace KJS {
     
    4446class ExecState;
    4547class JSObject;
    46 
    47 /**
    48  * Primitive types
    49  */
    50 enum Type {
    51     UnspecifiedType   = 0,
    52     UndefinedType     = 1,
    53     NullType          = 2,
    54     BooleanType       = 3,
    55     StringType        = 4,
    56     NumberType        = 5,
    57     ObjectType        = 6,
    58     GetterSetterType  = 7
    59 };
    6048
    6149/**
     
    7765public:
    7866    // Querying the type.
    79     Type type() const;
     67    JSType type() const;
    8068    bool isUndefined() const;
    8169    bool isNull() const;
     
    8977    // Extracting the value.
    9078    bool getBoolean(bool&) const;
     79    bool getBoolean() const; // false if not a boolean
    9180    bool getNumber(double&) const;
    9281    double getNumber() const; // NaN if not a number
     
    10089
    10190    // Basic conversions.
    102     JSValue *toPrimitive(ExecState *exec, Type preferredType = UnspecifiedType) const;
     91    JSValue *toPrimitive(ExecState *exec, JSType preferredType = UnspecifiedType) const;
    10392    bool toBoolean(ExecState *exec) const;
    10493    double toNumber(ExecState *exec) const;
     
    128117class JSCell : public JSValue {
    129118    friend class Collector;
    130     friend class UndefinedImp;
    131     friend class NullImp;
    132     friend class BooleanImp;
    133119    friend class NumberImp;
    134120    friend class StringImp;
     
    140126public:
    141127    // Querying the type.
    142     virtual Type type() const = 0;
    143     bool isBoolean() const;
     128    virtual JSType type() const = 0;
    144129    bool isNumber() const;
    145130    bool isString() const;
     
    148133
    149134    // Extracting the value.
    150     bool getBoolean(bool&) const;
    151135    bool getNumber(double&) const;
    152136    double getNumber() const; // NaN if not a number
     
    160144
    161145    // Basic conversions.
    162     virtual JSValue *toPrimitive(ExecState *exec, Type preferredType = UnspecifiedType) const = 0;
     146    virtual JSValue *toPrimitive(ExecState *exec, JSType preferredType = UnspecifiedType) const = 0;
    163147    virtual bool toBoolean(ExecState *exec) const = 0;
    164148    virtual double toNumber(ExecState *exec) const = 0;
     
    175159};
    176160
    177 JSCell *jsUndefined();
    178 JSCell *jsNull();
    179 
    180 JSCell *jsBoolean(bool);
    181 
     161JSValue *jsUndefined();
     162JSValue *jsNull();
     163
     164JSValue *jsBoolean(bool);
     165
     166JSValue *jsNumberCell(double);
    182167JSValue *jsNumber(double);
    183168JSValue *jsNaN();
     
    186171JSCell *jsString(const char * = ""); // returns empty string if passed 0
    187172
    188 extern const double NaN;
    189 extern const double Inf;
    190 
    191 class ConstantValues {
    192 public:
    193     static JSCell *undefined;
    194     static JSCell *null;
    195     static JSCell *jsFalse;
    196     static JSCell *jsTrue;
    197 
    198     static void initIfNeeded();
    199     static void mark();
    200 };
    201 
    202 inline JSCell *jsUndefined()
    203 {
    204     return ConstantValues::undefined;
    205 }
    206 
    207 inline JSCell *jsNull()
    208 {
    209     return ConstantValues::null;
    210 }
    211 
    212 inline JSCell *jsBoolean(bool b)
    213 {
    214     return b ? ConstantValues::jsTrue : ConstantValues::jsFalse;
     173extern double NaN;
     174extern double Inf;
     175
     176
     177inline JSValue *jsUndefined()
     178{
     179    return JSImmediate::undefinedImmediate();
     180}
     181
     182inline JSValue *jsNull()
     183{
     184    return JSImmediate::nullImmediate();
    215185}
    216186
    217187inline JSValue *jsNaN()
    218188{
    219     return SimpleNumber::make(NaN);
     189    return JSImmediate::NaNImmediate();
     190}
     191
     192inline JSValue *jsBoolean(bool b)
     193{
     194    return b ? JSImmediate::trueImmediate() : JSImmediate::falseImmediate();
     195}
     196
     197inline JSValue *jsNumber(double d)
     198{
     199    JSValue *v = JSImmediate::fromDouble(d);
     200    return v ? v : jsNumberCell(d);
    220201}
    221202
     
    237218}
    238219
    239 inline bool JSCell::isBoolean() const
    240 {
    241     return type() == BooleanType;
    242 }
    243 
    244220inline bool JSCell::isNumber() const
    245221{
     
    269245inline JSCell *JSValue::downcast()
    270246{
    271     assert(!SimpleNumber::is(this));
     247    ASSERT(!JSImmediate::isImmediate(this));
    272248    return static_cast<JSCell *>(this);
    273249}
     
    275251inline const JSCell *JSValue::downcast() const
    276252{
    277     assert(!SimpleNumber::is(this));
     253    ASSERT(!JSImmediate::isImmediate(this));
    278254    return static_cast<const JSCell *>(this);
    279255}
     
    291267inline bool JSValue::isUndefinedOrNull() const
    292268{
    293     return this == jsUndefined() || this == jsNull();
     269    return JSImmediate::isUndefinedOrNull(this);
    294270}
    295271
    296272inline bool JSValue::isBoolean() const
    297273{
    298     return !SimpleNumber::is(this) && downcast()->isBoolean();
     274    return JSImmediate::isBoolean(this);
    299275}
    300276
    301277inline bool JSValue::isNumber() const
    302278{
    303     return SimpleNumber::is(this) || downcast()->isNumber();
     279    return JSImmediate::isNumber(this) || !JSImmediate::isImmediate(this) && downcast()->isNumber();
    304280}
    305281
    306282inline bool JSValue::isString() const
    307283{
    308     return !SimpleNumber::is(this) && downcast()->isString();
     284    return !JSImmediate::isImmediate(this) && downcast()->isString();
    309285}
    310286
    311287inline bool JSValue::isObject() const
    312288{
    313     return !SimpleNumber::is(this) && downcast()->isObject();
     289    return !JSImmediate::isImmediate(this) && downcast()->isObject();
    314290}
    315291
    316292inline bool JSValue::getBoolean(bool& v) const
    317293{
    318     return !SimpleNumber::is(this) && downcast()->getBoolean(v);
     294    if (JSImmediate::isBoolean(this)) {
     295        v = JSImmediate::toBoolean(this);
     296        return true;
     297    }
     298   
     299    return false;
     300}
     301
     302inline bool JSValue::getBoolean() const
     303{
     304    return JSImmediate::isBoolean(this) ? JSImmediate::toBoolean(this) : false;
    319305}
    320306
    321307inline bool JSValue::getNumber(double& v) const
    322308{
    323     if (SimpleNumber::is(this)) {
    324         v = SimpleNumber::value(this);
     309    if (JSImmediate::isImmediate(this)) {
     310        v = JSImmediate::toDouble(this);
    325311        return true;
    326312    }
     
    330316inline double JSValue::getNumber() const
    331317{
    332     return SimpleNumber::is(this) ? SimpleNumber::value(this) : downcast()->getNumber();
     318    return JSImmediate::isImmediate(this) ? JSImmediate::toDouble(this) : downcast()->getNumber();
    333319}
    334320
    335321inline bool JSValue::getString(UString& s) const
    336322{
    337     return !SimpleNumber::is(this) && downcast()->getString(s);
     323    return !JSImmediate::isImmediate(this) && downcast()->getString(s);
    338324}
    339325
    340326inline UString JSValue::getString() const
    341327{
    342     return SimpleNumber::is(this) ? UString() : downcast()->getString();
     328    return JSImmediate::isImmediate(this) ? UString() : downcast()->getString();
    343329}
    344330
    345331inline JSObject *JSValue::getObject()
    346332{
    347     return SimpleNumber::is(this) ? 0 : downcast()->getObject();
     333    return JSImmediate::isImmediate(this) ? 0 : downcast()->getObject();
    348334}
    349335
    350336inline const JSObject *JSValue::getObject() const
    351337{
    352     return SimpleNumber::is(this) ? 0 : downcast()->getObject();
     338    return JSImmediate::isImmediate(this) ? 0 : downcast()->getObject();
    353339}
    354340
    355341inline bool JSValue::getUInt32(uint32_t& v) const
    356342{
    357     if (SimpleNumber::is(this)) {
    358         double d = SimpleNumber::value(this);
     343    if (JSImmediate::isImmediate(this)) {
     344        double d = JSImmediate::toDouble(this);
    359345        if (!(d >= 0) || d > 0xFFFFFFFFUL) // true for NaN
    360346            return false;
     
    367353inline void JSValue::mark()
    368354{
    369     if (!SimpleNumber::is(this))
    370         downcast()->mark();
     355    ASSERT(!JSImmediate::isImmediate(this)); // callers should check !marked() before calling mark()
     356    downcast()->mark();
    371357}
    372358
    373359inline bool JSValue::marked() const
    374360{
    375     return SimpleNumber::is(this) || downcast()->marked();
    376 }
    377 
    378 inline Type JSValue::type() const
    379 {
    380     return SimpleNumber::is(this) ? NumberType : downcast()->type();
    381 }
    382 
    383 inline JSValue *JSValue::toPrimitive(ExecState *exec, Type preferredType) const
    384 {
    385     return SimpleNumber::is(this) ? const_cast<JSValue *>(this) : downcast()->toPrimitive(exec, preferredType);
     361    return JSImmediate::isImmediate(this) || downcast()->marked();
     362}
     363
     364inline JSType JSValue::type() const
     365{
     366    return JSImmediate::isImmediate(this) ? JSImmediate::type(this) : downcast()->type();
     367}
     368
     369inline JSValue *JSValue::toPrimitive(ExecState *exec, JSType preferredType) const
     370{
     371    return JSImmediate::isImmediate(this) ? const_cast<JSValue *>(this) : downcast()->toPrimitive(exec, preferredType);
    386372}
    387373
    388374inline bool JSValue::toBoolean(ExecState *exec) const
    389375{
    390     if (SimpleNumber::is(this)) {
    391         double d = SimpleNumber::value(this);
    392         return d < 0 || d > 0; // false for NaN
    393     }
    394 
    395     return downcast()->toBoolean(exec);
     376    return JSImmediate::isImmediate(this) ? JSImmediate::toBoolean(this) : downcast()->toBoolean(exec);
    396377}
    397378
    398379inline double JSValue::toNumber(ExecState *exec) const
    399380{
    400     return SimpleNumber::is(this) ? SimpleNumber::value(this) : downcast()->toNumber(exec);
     381    return JSImmediate::isImmediate(this) ? JSImmediate::toDouble(this) : downcast()->toNumber(exec);
    401382}
    402383
    403384inline UString JSValue::toString(ExecState *exec) const
    404385{
    405     if (SimpleNumber::is(this)) {
    406         double d = SimpleNumber::value(this);
    407         if (d == 0.0) // +0.0 or -0.0
    408             d = 0.0;
    409         return UString::from(d);
    410     }
    411 
    412     return downcast()->toString(exec);
     386    return JSImmediate::isImmediate(this) ? JSImmediate::toString(this) : downcast()->toString(exec);
    413387}
    414388
Note: See TracChangeset for help on using the changeset viewer.