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/internal.cpp

    r12593 r12728  
    7575#endif
    7676
    77 // ------------------------------ UndefinedImp ---------------------------------
    78 
    79 JSValue *UndefinedImp::toPrimitive(ExecState *, Type) const
    80 {
    81   return const_cast<UndefinedImp *>(this);
    82 }
    83 
    84 bool UndefinedImp::toBoolean(ExecState *) const
    85 {
    86   return false;
    87 }
    88 
    89 double UndefinedImp::toNumber(ExecState *) const
    90 {
    91   return NaN;
    92 }
    93 
    94 UString UndefinedImp::toString(ExecState *) const
    95 {
    96   return "undefined";
    97 }
    98 
    99 JSObject *UndefinedImp::toObject(ExecState *exec) const
    100 {
    101   return throwError(exec, TypeError, "Undefined value");
    102 }
    103 
    104 // ------------------------------ NullImp --------------------------------------
    105 
    106 JSValue *NullImp::toPrimitive(ExecState *, Type) const
    107 {
    108   return const_cast<NullImp *>(this);
    109 }
    110 
    111 bool NullImp::toBoolean(ExecState *) const
    112 {
    113   return false;
    114 }
    115 
    116 double NullImp::toNumber(ExecState *) const
    117 {
    118   return 0.0;
    119 }
    120 
    121 UString NullImp::toString(ExecState *) const
    122 {
    123   return "null";
    124 }
    125 
    126 JSObject *NullImp::toObject(ExecState *exec) const
    127 {
    128   return throwError(exec, TypeError, "Null value");
    129 }
    130 
    131 // ------------------------------ BooleanImp -----------------------------------
    132 
    133 JSValue *BooleanImp::toPrimitive(ExecState *, Type) const
    134 {
    135   return const_cast<BooleanImp *>(this);
    136 }
    137 
    138 bool BooleanImp::toBoolean(ExecState *) const
     77// ------------------------------ StringImp ------------------------------------
     78
     79JSValue *StringImp::toPrimitive(ExecState *, JSType) const
     80{
     81  return const_cast<StringImp *>(this);
     82}
     83
     84bool StringImp::toBoolean(ExecState *) const
     85{
     86  return (val.size() > 0);
     87}
     88
     89double StringImp::toNumber(ExecState *) const
     90{
     91  return val.toDouble();
     92}
     93
     94UString StringImp::toString(ExecState *) const
    13995{
    14096  return val;
    14197}
    14298
    143 double BooleanImp::toNumber(ExecState *) const
    144 {
    145   return val ? 1.0 : 0.0;
    146 }
    147 
    148 UString BooleanImp::toString(ExecState *) const
    149 {
    150   return val ? "true" : "false";
    151 }
    152 
    153 JSObject *BooleanImp::toObject(ExecState *exec) const
    154 {
    155   List args;
    156   args.append(const_cast<BooleanImp*>(this));
    157   return static_cast<JSObject *>(exec->lexicalInterpreter()->builtinBoolean()->construct(exec,args));
    158 }
    159 
    160 // ------------------------------ StringImp ------------------------------------
    161 
    162 JSValue *StringImp::toPrimitive(ExecState *, Type) const
    163 {
    164   return const_cast<StringImp *>(this);
    165 }
    166 
    167 bool StringImp::toBoolean(ExecState *) const
    168 {
    169   return (val.size() > 0);
    170 }
    171 
    172 double StringImp::toNumber(ExecState *) const
    173 {
    174   return val.toDouble();
    175 }
    176 
    177 UString StringImp::toString(ExecState *) const
    178 {
    179   return val;
    180 }
    181 
    18299JSObject *StringImp::toObject(ExecState *exec) const
    183100{
     
    187104// ------------------------------ NumberImp ------------------------------------
    188105
    189 JSValue *NumberImp::toPrimitive(ExecState *, Type) const
     106JSValue *NumberImp::toPrimitive(ExecState *, JSType) const
    190107{
    191108  return const_cast<NumberImp *>(this);
     
    194111bool NumberImp::toBoolean(ExecState *) const
    195112{
    196   return !((val == 0) /* || (iVal() == N0) */ || isNaN(val));
     113  return val < 0.0 || val > 0.0; // false for NaN
    197114}
    198115
     
    216133}
    217134
     135// FIXME: We can optimize this to work like JSValue::getUInt32. I'm ignoring it for now
     136// because it never shows up on profiles.
    218137bool NumberImp::getUInt32(uint32_t& uint32) const
    219138{
     
    231150}
    232151
    233 JSValue *GetterSetterImp::toPrimitive(ExecState *exec, Type type) const
     152JSValue *GetterSetterImp::toPrimitive(ExecState *exec, JSType) const
    234153{
    235154    assert(false);
Note: See TracChangeset for help on using the changeset viewer.