Changeset 34921 in webkit for trunk/JavaScriptCore/kjs


Ignore:
Timestamp:
Jul 1, 2008, 10:32:44 AM (17 years ago)
Author:
[email protected]
Message:

JavaScriptCore:

2008-07-01 Sam Weinig <[email protected]>

Reviewed by Darin Adler.

Split JSCell and JSNumberCell class declarations out of JSValue.h

  • GNUmakefile.am:
  • JavaScriptCore.pri:
  • JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
  • JavaScriptCore.xcodeproj/project.pbxproj:
  • JavaScriptCoreSources.bkl:
  • VM/JSPropertyNameIterator.h:
  • kjs/AllInOneFile.cpp:
  • kjs/JSCell.cpp: Copied from JavaScriptCore/kjs/JSValue.cpp.
  • kjs/JSCell.h: Copied from JavaScriptCore/kjs/JSValue.h. (KJS::JSValue::getJSNumber):
  • kjs/JSNumberCell.cpp:
  • kjs/JSNumberCell.h: Copied from JavaScriptCore/kjs/JSValue.h.
  • kjs/JSObject.h:
  • kjs/JSString.cpp: (KJS::jsString): (KJS::jsOwnedString):
  • kjs/JSString.h: (KJS::JSValue::toThisJSString):
  • kjs/JSValue.cpp:
  • kjs/JSValue.h:

WebCore:

2008-07-01 Sam Weinig <[email protected]>

Reviewed by Darin Adler.

Split JSCell and JSNumberCell class declarations out of JSValue.h

  • ForwardingHeaders/kjs/JSNumberCell.h: Added.
  • bindings/scripts/CodeGeneratorJS.pm:
  • bridge/c/c_instance.cpp:
Location:
trunk/JavaScriptCore/kjs
Files:
7 edited
3 copied

Legend:

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

    r34897 r34921  
    9191#include "ustring.cpp"
    9292#include "JSValue.cpp"
     93#include "JSCell.cpp"
    9394#include "JSVariableObject.cpp"
    9495#include "wtf/FastMalloc.cpp"
  • trunk/JavaScriptCore/kjs/JSCell.cpp

    r34892 r34921  
    2222
    2323#include "config.h"
    24 #include "JSValue.h"
     24#include "JSCell.h"
    2525
    2626#include "JSFunction.h"
    27 #include "nodes.h"
    28 #include <stdio.h>
    29 #include <string.h>
     27#include "JSString.h"
     28#include "JSObject.h"
    3029#include <wtf/MathExtras.h>
    3130
     
    7877#endif // !(defined NAN && defined INFINITY)
    7978
    80 static const double D16 = 65536.0;
    81 static const double D32 = 4294967296.0;
    82 
    8379void* JSCell::operator new(size_t size, ExecState* exec)
    8480{
     
    10399{
    104100    return false;
    105 }
    106 
    107 // ECMA 9.4
    108 double JSValue::toInteger(ExecState* exec) const
    109 {
    110     int32_t i;
    111     if (getTruncatedInt32(i))
    112         return i;
    113     double d = toNumber(exec);
    114     return isnan(d) ? 0.0 : trunc(d);
    115 }
    116 
    117 double JSValue::toIntegerPreserveNaN(ExecState* exec) const
    118 {
    119     int32_t i;
    120     if (getTruncatedInt32(i))
    121         return i;
    122     return trunc(toNumber(exec));
    123 }
    124 
    125 int32_t JSValue::toInt32SlowCase(double d, bool& ok)
    126 {
    127     ok = true;
    128 
    129     if (d >= -D32 / 2 && d < D32 / 2)
    130         return static_cast<int32_t>(d);
    131 
    132     if (isnan(d) || isinf(d)) {
    133         ok = false;
    134         return 0;
    135     }
    136 
    137     double d32 = fmod(trunc(d), D32);
    138     if (d32 >= D32 / 2)
    139         d32 -= D32;
    140     else if (d32 < -D32 / 2)
    141         d32 += D32;
    142     return static_cast<int32_t>(d32);
    143 }
    144 
    145 int32_t JSValue::toInt32SlowCase(ExecState* exec, bool& ok) const
    146 {
    147     return JSValue::toInt32SlowCase(toNumber(exec), ok);
    148 }
    149 
    150 uint32_t JSValue::toUInt32SlowCase(double d, bool& ok)
    151 {
    152     ok = true;
    153 
    154     if (d >= 0.0 && d < D32)
    155         return static_cast<uint32_t>(d);
    156 
    157     if (isnan(d) || isinf(d)) {
    158         ok = false;
    159         return 0;
    160     }
    161 
    162     double d32 = fmod(trunc(d), D32);
    163     if (d32 < 0)
    164         d32 += D32;
    165     return static_cast<uint32_t>(d32);
    166 }
    167 
    168 uint32_t JSValue::toUInt32SlowCase(ExecState* exec, bool& ok) const
    169 {
    170     return JSValue::toUInt32SlowCase(toNumber(exec), ok);
    171 }
    172 
    173 float JSValue::toFloat(ExecState* exec) const
    174 {
    175     return static_cast<float>(toNumber(exec));
    176101}
    177102
     
    291216}
    292217
    293 JSString* jsString(ExecState* exec, const char* s)
    294 {
    295     return new (exec) JSString(s ? s : "");
    296 }
    297 
    298 JSString* jsString(ExecState* exec, const UString& s)
    299 {
    300     return s.isNull() ? new (exec) JSString("") : new (exec) JSString(s);
    301 }
    302 
    303 JSString* jsOwnedString(ExecState* exec, const UString& s)
    304 {
    305     return s.isNull() ? new (exec) JSString("", JSString::HasOtherOwner) : new (exec) JSString(s, JSString::HasOtherOwner);
    306 }
    307 
    308 JSValue* call(ExecState* exec, JSValue* functionObject, CallType callType, const CallData& callData, JSValue* thisValue, const ArgList& args)
    309 {
    310     if (callType == CallTypeNative)
    311         return callData.native.function(exec, static_cast<JSObject*>(functionObject), thisValue, args);
    312     ASSERT(callType == CallTypeJS);
    313     // FIXME: Can this be done more efficiently using the callData?
    314     return static_cast<JSFunction*>(functionObject)->call(exec, thisValue, args);
    315 }
    316 
    317 JSObject* construct(ExecState* exec, JSValue* object, ConstructType constructType, const ConstructData& constructData, const ArgList& args)
    318 {
    319     if (constructType == ConstructTypeNative)
    320         return constructData.native.function(exec, static_cast<JSObject*>(object), args);
    321     ASSERT(constructType == ConstructTypeJS);
    322     // FIXME: Can this be done more efficiently using the constructData?
    323     return static_cast<JSFunction*>(object)->construct(exec, args);
    324 }
    325 
    326218} // namespace KJS
  • trunk/JavaScriptCore/kjs/JSCell.h

    r34892 r34921  
    2121 */
    2222
    23 #ifndef JSValue_h
    24 #define JSValue_h
    25 
    26 #include "CallData.h"
    27 #include "ConstructData.h"
    28 #include "ExecState.h"
    29 #include "JSImmediate.h"
     23#ifndef JSCell_h
     24#define JSCell_h
     25
     26#include "JSValue.h"
    3027#include "collector.h"
    31 #include "ustring.h"
    32 #include <stddef.h> // for size_t
    3328
    3429namespace KJS {
    35 
    36 class ExecState;
    37 class Identifier;
    38 class JSCell;
    39 class JSObject;
    40 class JSString;
    41 class PropertySlot;
    42 
    43 struct ClassInfo;
    44 struct Instruction;
    45 
    46 /**
    47  * JSValue is the base type for all primitives (Undefined, Null, Boolean,
    48  * String, Number) and objects in ECMAScript.
    49  *
    50  * Note: you should never inherit from JSValue as it is for primitive types
    51  * only (all of which are provided internally by KJS). Instead, inherit from
    52  * JSObject.
    53  */
    54 class JSValue : Noncopyable {
    55     friend class JSCell; // so it can derive from this class
    56     friend class Heap; // so it can call asCell()
    57 private:
    58     JSValue();
    59     virtual ~JSValue();
    60 
    61 public:
    62     // Querying the type.
    63     JSType type() const;
    64     bool isUndefined() const;
    65     bool isNull() const;
    66     bool isUndefinedOrNull() const;
    67     bool isBoolean() const;
    68     bool isNumber() const;
    69     bool isString() const;
    70     bool isObject() const;
    71     bool isObject(const ClassInfo*) const; // FIXME: Merge with inherits.
    72 
    73     // Extracting the value.
    74     bool getBoolean(bool&) const;
    75     bool getBoolean() const; // false if not a boolean
    76     bool getNumber(double&) const;
    77     double getNumber() const; // NaN if not a number
    78     double uncheckedGetNumber() const;
    79     bool getString(UString&) const;
    80     UString getString() const; // null string if not a string
    81     JSObject* getObject(); // NULL if not an object
    82     const JSObject* getObject() const; // NULL if not an object
    83 
    84     CallType getCallData(CallData&);
    85     ConstructType getConstructData(ConstructData&);
    86 
    87     // Extracting integer values.
    88     bool getUInt32(uint32_t&) const;
    89     bool getTruncatedInt32(int32_t&) const;
    90     bool getTruncatedUInt32(uint32_t&) const;
    91    
    92     // Basic conversions.
    93     JSValue* toPrimitive(ExecState*, JSType preferredType = UnspecifiedType) const;
    94     bool getPrimitiveNumber(ExecState*, double& number, JSValue*&);
    95 
    96     bool toBoolean(ExecState*) const;
    97 
    98     // toNumber conversion is expected to be side effect free if an exception has
    99     // been set in the ExecState already.
    100     double toNumber(ExecState*) const;
    101     JSValue* toJSNumber(ExecState*) const; // Fast path for when you expect that the value is an immediate number.
    102     UString toString(ExecState*) const;
    103     JSObject* toObject(ExecState*) const;
    104 
    105     // Integer conversions.
    106     double toInteger(ExecState*) const;
    107     double toIntegerPreserveNaN(ExecState*) const;
    108     int32_t toInt32(ExecState*) const;
    109     int32_t toInt32(ExecState*, bool& ok) const;
    110     uint32_t toUInt32(ExecState*) const;
    111     uint32_t toUInt32(ExecState*, bool& ok) const;
    112 
    113     // These are identical logic to above, and faster than jsNumber(number)->toInt32(exec)
    114     static int32_t toInt32(double);
    115     static int32_t toUInt32(double);
    116 
    117     // Floating point conversions.
    118     float toFloat(ExecState*) const;
    119 
    120     // Garbage collection.
    121     void mark();
    122     bool marked() const;
    123 
    124     static int32_t toInt32SlowCase(double, bool& ok);
    125     static uint32_t toUInt32SlowCase(double, bool& ok);
    126 
    127     // Object operations, with the toObject operation included.
    128     JSValue* get(ExecState*, const Identifier& propertyName) const;
    129     JSValue* get(ExecState*, unsigned propertyName) const;
    130     void put(ExecState*, const Identifier& propertyName, JSValue*);
    131     void put(ExecState*, unsigned propertyName, JSValue*);
    132     bool deleteProperty(ExecState*, const Identifier& propertyName);
    133     bool deleteProperty(ExecState*, unsigned propertyName);
    134 
    135     JSObject* toThisObject(ExecState*) const;
    136     UString toThisString(ExecState*) const;
    137     JSString* toThisJSString(ExecState*);
    138 
    139     JSValue* getJSNumber(); // 0 if this is not a JSNumber or number object
    140 
    141 private:
    142     bool getPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
    143     bool getPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
    144     int32_t toInt32SlowCase(ExecState*, bool& ok) const;
    145     uint32_t toUInt32SlowCase(ExecState*, bool& ok) const;
    146 
    147     // Implementation details.
    148     JSCell* asCell();
    149     const JSCell* asCell() const;
    150 };
    15130
    15231class JSCell : public JSValue {
     
    21796};
    21897
    219 class JSNumberCell : public JSCell {
    220     friend JSValue* jsNumberCell(ExecState*, double);
    221 public:
    222     double value() const { return val; }
    223 
    224     virtual JSType type() const;
    225 
    226     virtual JSValue* toPrimitive(ExecState*, JSType preferred = UnspecifiedType) const;
    227     virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue*& value);
    228     virtual bool toBoolean(ExecState*) const;
    229     virtual double toNumber(ExecState*) const;
    230     virtual UString toString(ExecState*) const;
    231     virtual JSObject* toObject(ExecState*) const;
    232 
    233     virtual UString toThisString(ExecState*) const;
    234     virtual JSObject* toThisObject(ExecState*) const;
    235     virtual JSValue* getJSNumber();
    236 
    237     void* operator new(size_t size, ExecState* exec)
    238     {
    239 #ifdef JAVASCRIPTCORE_BUILDING_ALL_IN_ONE_FILE
    240         return exec->heap()->inlineAllocateNumber(size);
    241 #else
    242         return exec->heap()->allocateNumber(size);
    243 #endif
    244     }
    245 
    246 private:
    247     JSNumberCell(double v)
    248         : val(v)
    249     {
    250     }
    251 
    252     virtual bool getUInt32(uint32_t&) const;
    253     virtual bool getTruncatedInt32(int32_t&) const;
    254     virtual bool getTruncatedUInt32(uint32_t&) const;
    255 
    256     double val;
    257 };
    258 
    259 JSString* jsString(ExecState*, const UString&); // returns empty string if passed null string
    260 JSString* jsString(ExecState*, const char* = ""); // returns empty string if passed 0
    261 
    262 // should be used for strings that are owned by an object that will
    263 // likely outlive the JSValue this makes, such as the parse tree or a
    264 // DOM object that contains a UString
    265 JSString* jsOwnedString(ExecState*, const UString&);
    266 
    267 extern const double NaN;
    268 extern const double Inf;
    269 
    270 // Beware marking this function ALWAYS_INLINE: It takes a PIC branch, so
    271 // inlining it may not always be a win.
    272 inline JSValue* jsNumberCell(ExecState* exec, double d)
    273 {
    274     return new (exec) JSNumberCell(d);
    275 }
    276 
    277 inline JSValue* jsNaN(ExecState* exec)
    278 {
    279     return jsNumberCell(exec, NaN);
    280 }
    281 
    282 ALWAYS_INLINE JSValue* jsNumber(ExecState* exec, double d)
    283 {
    284     JSValue* v = JSImmediate::from(d);
    285     return v ? v : jsNumberCell(exec, d);
    286 }
    287 
    288 ALWAYS_INLINE JSValue* jsNumber(ExecState* exec, int i)
    289 {
    290     JSValue* v = JSImmediate::from(i);
    291     return v ? v : jsNumberCell(exec, i);
    292 }
    293 
    294 ALWAYS_INLINE JSValue* jsNumber(ExecState* exec, unsigned i)
    295 {
    296     JSValue* v = JSImmediate::from(i);
    297     return v ? v : jsNumberCell(exec, i);
    298 }
    299 
    300 ALWAYS_INLINE JSValue* jsNumber(ExecState* exec, long i)
    301 {
    302     JSValue* v = JSImmediate::from(i);
    303     return v ? v : jsNumberCell(exec, i);
    304 }
    305 
    306 ALWAYS_INLINE JSValue* jsNumber(ExecState* exec, unsigned long i)
    307 {
    308     JSValue* v = JSImmediate::from(i);
    309     return v ? v : jsNumberCell(exec, i);
    310 }
    311 
    312 ALWAYS_INLINE JSValue* jsNumber(ExecState* exec, long long i)
    313 {
    314     JSValue* v = JSImmediate::from(i);
    315     return v ? v : jsNumberCell(exec, static_cast<double>(i));
    316 }
    317 
    318 ALWAYS_INLINE JSValue* jsNumber(ExecState* exec, unsigned long long i)
    319 {
    320     JSValue* v = JSImmediate::from(i);
    321     return v ? v : jsNumberCell(exec, static_cast<double>(i));
    322 }
    323 
    324 inline JSValue::JSValue()
    325 {
    326 }
    327 
    328 inline JSValue::~JSValue()
    329 {
    330 }
    331 
    33298inline JSCell::JSCell()
    33399{
     
    375141}
    376142
    377 inline bool JSValue::isUndefined() const
    378 {
    379     return this == jsUndefined();
    380 }
    381 
    382 inline bool JSValue::isNull() const
    383 {
    384     return this == jsNull();
    385 }
    386 
    387 inline bool JSValue::isUndefinedOrNull() const
    388 {
    389     return JSImmediate::isUndefinedOrNull(this);
    390 }
    391 
    392 inline bool JSValue::isBoolean() const
    393 {
    394     return JSImmediate::isBoolean(this);
    395 }
     143
     144// --- JSValue inlines ----------------------------
    396145
    397146inline bool JSValue::isNumber() const
     
    408157{
    409158    return !JSImmediate::isImmediate(this) && asCell()->isObject();
    410 }
    411 
    412 inline bool JSValue::getBoolean(bool& v) const
    413 {
    414     if (JSImmediate::isBoolean(this)) {
    415         v = JSImmediate::toBoolean(this);
    416         return true;
    417     }
    418    
    419     return false;
    420 }
    421 
    422 inline bool JSValue::getBoolean() const
    423 {
    424     return JSImmediate::isBoolean(this) ? JSImmediate::toBoolean(this) : false;
    425159}
    426160
     
    437171{
    438172    return JSImmediate::isImmediate(this) ? JSImmediate::toDouble(this) : asCell()->getNumber();
    439 }
    440 
    441 inline double JSValue::uncheckedGetNumber() const
    442 {
    443     ASSERT(JSImmediate::isImmediate(this) || asCell()->isNumber());
    444     return JSImmediate::isImmediate(this) ? JSImmediate::toDouble(this) : static_cast<const JSNumberCell*>(this)->value();
    445173}
    446174
     
    531259}
    532260
    533 ALWAYS_INLINE JSValue* JSValue::toJSNumber(ExecState* exec) const
    534 {
    535     return JSImmediate::isNumber(this) ? const_cast<JSValue*>(this) : jsNumber(exec, this->toNumber(exec));
    536 }
    537 
    538261inline UString JSValue::toString(ExecState *exec) const
    539262{
     
    544267{
    545268    return JSImmediate::isImmediate(this) ? JSImmediate::toObject(this, exec) : asCell()->toObject(exec);
    546 }
    547 
    548 ALWAYS_INLINE int32_t JSValue::toInt32(ExecState* exec) const
    549 {
    550     int32_t i;
    551     if (getTruncatedInt32(i))
    552         return i;
    553     bool ok;
    554     return toInt32SlowCase(exec, ok);
    555 }
    556 
    557 inline uint32_t JSValue::toUInt32(ExecState* exec) const
    558 {
    559     uint32_t i;
    560     if (getTruncatedUInt32(i))
    561         return i;
    562     bool ok;
    563     return toUInt32SlowCase(exec, ok);
    564 }
    565 
    566 inline int32_t JSValue::toInt32(double val)
    567 {
    568     if (!(val >= -2147483648.0 && val < 2147483648.0)) {
    569         bool ignored;
    570         return toInt32SlowCase(val, ignored);
    571     }
    572     return static_cast<int32_t>(val);
    573 }
    574 
    575 inline int32_t JSValue::toUInt32(double val)
    576 {
    577     if (!(val >= 0.0 && val < 4294967296.0)) {
    578         bool ignored;
    579         return toUInt32SlowCase(val, ignored);
    580     }
    581     return static_cast<uint32_t>(val);
    582 }
    583 
    584 inline int32_t JSValue::toInt32(ExecState* exec, bool& ok) const
    585 {
    586     int32_t i;
    587     if (getTruncatedInt32(i)) {
    588         ok = true;
    589         return i;
    590     }
    591     return toInt32SlowCase(exec, ok);
    592 }
    593 
    594 inline uint32_t JSValue::toUInt32(ExecState* exec, bool& ok) const
    595 {
    596     uint32_t i;
    597     if (getTruncatedUInt32(i)) {
    598         ok = true;
    599         return i;
    600     }
    601     return toUInt32SlowCase(exec, ok);
    602269}
    603270
     
    614281}
    615282
    616 inline JSString* JSValue::toThisJSString(ExecState* exec)
    617 {
    618     return JSImmediate::isImmediate(this) ? jsString(exec, JSImmediate::toString(this)) : asCell()->toThisJSString(exec);
    619 }
    620 
    621283inline JSValue* JSValue::getJSNumber()
    622284{
     285
    623286    return JSImmediate::isNumber(this) ? this : (JSImmediate::isImmediate(this) ? 0 : asCell()->getJSNumber());
    624287}
     
    626289} // namespace KJS
    627290
    628 #endif // JSValue_h
     291#endif // JSCell_h
  • trunk/JavaScriptCore/kjs/JSNumberCell.cpp

    r34893 r34921  
    2222
    2323#include "config.h"
    24 #include "JSValue.h"
     24#include "JSNumberCell.h"
    2525
    2626#include "JSType.h"
  • trunk/JavaScriptCore/kjs/JSNumberCell.h

    r34892 r34921  
    2121 */
    2222
    23 #ifndef JSValue_h
    24 #define JSValue_h
     23#ifndef JSNumberCell_h
     24#define JSNumberCell_h
    2525
    2626#include "CallData.h"
    2727#include "ConstructData.h"
    2828#include "ExecState.h"
     29#include "JSCell.h"
    2930#include "JSImmediate.h"
    3031#include "collector.h"
     
    4344struct ClassInfo;
    4445struct Instruction;
    45 
    46 /**
    47  * JSValue is the base type for all primitives (Undefined, Null, Boolean,
    48  * String, Number) and objects in ECMAScript.
    49  *
    50  * Note: you should never inherit from JSValue as it is for primitive types
    51  * only (all of which are provided internally by KJS). Instead, inherit from
    52  * JSObject.
    53  */
    54 class JSValue : Noncopyable {
    55     friend class JSCell; // so it can derive from this class
    56     friend class Heap; // so it can call asCell()
    57 private:
    58     JSValue();
    59     virtual ~JSValue();
    60 
    61 public:
    62     // Querying the type.
    63     JSType type() const;
    64     bool isUndefined() const;
    65     bool isNull() const;
    66     bool isUndefinedOrNull() const;
    67     bool isBoolean() const;
    68     bool isNumber() const;
    69     bool isString() const;
    70     bool isObject() const;
    71     bool isObject(const ClassInfo*) const; // FIXME: Merge with inherits.
    72 
    73     // Extracting the value.
    74     bool getBoolean(bool&) const;
    75     bool getBoolean() const; // false if not a boolean
    76     bool getNumber(double&) const;
    77     double getNumber() const; // NaN if not a number
    78     double uncheckedGetNumber() const;
    79     bool getString(UString&) const;
    80     UString getString() const; // null string if not a string
    81     JSObject* getObject(); // NULL if not an object
    82     const JSObject* getObject() const; // NULL if not an object
    83 
    84     CallType getCallData(CallData&);
    85     ConstructType getConstructData(ConstructData&);
    86 
    87     // Extracting integer values.
    88     bool getUInt32(uint32_t&) const;
    89     bool getTruncatedInt32(int32_t&) const;
    90     bool getTruncatedUInt32(uint32_t&) const;
    91    
    92     // Basic conversions.
    93     JSValue* toPrimitive(ExecState*, JSType preferredType = UnspecifiedType) const;
    94     bool getPrimitiveNumber(ExecState*, double& number, JSValue*&);
    95 
    96     bool toBoolean(ExecState*) const;
    97 
    98     // toNumber conversion is expected to be side effect free if an exception has
    99     // been set in the ExecState already.
    100     double toNumber(ExecState*) const;
    101     JSValue* toJSNumber(ExecState*) const; // Fast path for when you expect that the value is an immediate number.
    102     UString toString(ExecState*) const;
    103     JSObject* toObject(ExecState*) const;
    104 
    105     // Integer conversions.
    106     double toInteger(ExecState*) const;
    107     double toIntegerPreserveNaN(ExecState*) const;
    108     int32_t toInt32(ExecState*) const;
    109     int32_t toInt32(ExecState*, bool& ok) const;
    110     uint32_t toUInt32(ExecState*) const;
    111     uint32_t toUInt32(ExecState*, bool& ok) const;
    112 
    113     // These are identical logic to above, and faster than jsNumber(number)->toInt32(exec)
    114     static int32_t toInt32(double);
    115     static int32_t toUInt32(double);
    116 
    117     // Floating point conversions.
    118     float toFloat(ExecState*) const;
    119 
    120     // Garbage collection.
    121     void mark();
    122     bool marked() const;
    123 
    124     static int32_t toInt32SlowCase(double, bool& ok);
    125     static uint32_t toUInt32SlowCase(double, bool& ok);
    126 
    127     // Object operations, with the toObject operation included.
    128     JSValue* get(ExecState*, const Identifier& propertyName) const;
    129     JSValue* get(ExecState*, unsigned propertyName) const;
    130     void put(ExecState*, const Identifier& propertyName, JSValue*);
    131     void put(ExecState*, unsigned propertyName, JSValue*);
    132     bool deleteProperty(ExecState*, const Identifier& propertyName);
    133     bool deleteProperty(ExecState*, unsigned propertyName);
    134 
    135     JSObject* toThisObject(ExecState*) const;
    136     UString toThisString(ExecState*) const;
    137     JSString* toThisJSString(ExecState*);
    138 
    139     JSValue* getJSNumber(); // 0 if this is not a JSNumber or number object
    140 
    141 private:
    142     bool getPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
    143     bool getPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
    144     int32_t toInt32SlowCase(ExecState*, bool& ok) const;
    145     uint32_t toUInt32SlowCase(ExecState*, bool& ok) const;
    146 
    147     // Implementation details.
    148     JSCell* asCell();
    149     const JSCell* asCell() const;
    150 };
    151 
    152 class JSCell : public JSValue {
    153     friend class Heap;
    154     friend class GetterSetter;
    155     friend class JSObject;
    156     friend class JSPropertyNameIterator;
    157     friend class JSValue;
    158     friend class JSNumberCell;
    159     friend class JSString;
    160 private:
    161     JSCell();
    162     virtual ~JSCell();
    163 
    164 public:
    165     // Querying the type.
    166     virtual JSType type() const = 0;
    167     bool isNumber() const;
    168     bool isString() const;
    169     bool isObject() const;
    170     bool isObject(const ClassInfo*) const; // FIXME: Merge with inherits.
    171 
    172     // Extracting the value.
    173     bool getNumber(double&) const;
    174     double getNumber() const; // NaN if not a number
    175     bool getString(UString&) const;
    176     UString getString() const; // null string if not a string
    177     JSObject* getObject(); // NULL if not an object
    178     const JSObject* getObject() const; // NULL if not an object
    179    
    180     virtual CallType getCallData(CallData&);
    181     virtual ConstructType getConstructData(ConstructData&);
    182 
    183     // Extracting integer values.
    184     virtual bool getUInt32(uint32_t&) const;
    185     virtual bool getTruncatedInt32(int32_t&) const;
    186     virtual bool getTruncatedUInt32(uint32_t&) const;
    187 
    188     // Basic conversions.
    189     virtual JSValue* toPrimitive(ExecState*, JSType preferredType = UnspecifiedType) const = 0;
    190     virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue*&) = 0;
    191     virtual bool toBoolean(ExecState*) const = 0;
    192     virtual double toNumber(ExecState*) const = 0;
    193     virtual UString toString(ExecState*) const = 0;
    194     virtual JSObject* toObject(ExecState*) const = 0;
    195 
    196     // Garbage collection.
    197     void* operator new(size_t, ExecState*);
    198     virtual void mark();
    199     bool marked() const;
    200 
    201     // Object operations, with the toObject operation included.
    202     virtual const ClassInfo* classInfo() const;
    203     virtual void put(ExecState*, const Identifier& propertyName, JSValue*);
    204     virtual void put(ExecState*, unsigned propertyName, JSValue*);
    205     virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
    206     virtual bool deleteProperty(ExecState*, unsigned propertyName);
    207 
    208     virtual JSObject* toThisObject(ExecState*) const;
    209     virtual UString toThisString(ExecState*) const;
    210     virtual JSString* toThisJSString(ExecState*);
    211     virtual JSValue* getJSNumber();
    212 
    213 private:
    214     // Base implementation, but for non-object classes implements getPropertySlot.
    215     virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
    216     virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
    217 };
    21846
    21947class JSNumberCell : public JSCell {
     
    25684    double val;
    25785};
    258 
    259 JSString* jsString(ExecState*, const UString&); // returns empty string if passed null string
    260 JSString* jsString(ExecState*, const char* = ""); // returns empty string if passed 0
    261 
    262 // should be used for strings that are owned by an object that will
    263 // likely outlive the JSValue this makes, such as the parse tree or a
    264 // DOM object that contains a UString
    265 JSString* jsOwnedString(ExecState*, const UString&);
    26686
    26787extern const double NaN;
     
    322142}
    323143
    324 inline JSValue::JSValue()
    325 {
    326 }
    327 
    328 inline JSValue::~JSValue()
    329 {
    330 }
    331 
    332 inline JSCell::JSCell()
    333 {
    334 }
    335 
    336 inline JSCell::~JSCell()
    337 {
    338 }
    339 
    340 inline bool JSCell::isNumber() const
    341 {
    342     return type() == NumberType;
    343 }
    344 
    345 inline bool JSCell::isString() const
    346 {
    347     return type() == StringType;
    348 }
    349 
    350 inline bool JSCell::isObject() const
    351 {
    352     return type() == ObjectType;
    353 }
    354 
    355 inline bool JSCell::marked() const
    356 {
    357     return Heap::isCellMarked(this);
    358 }
    359 
    360 inline void JSCell::mark()
    361 {
    362     return Heap::markCell(this);
    363 }
    364 
    365 ALWAYS_INLINE JSCell* JSValue::asCell()
    366 {
    367     ASSERT(!JSImmediate::isImmediate(this));
    368     return static_cast<JSCell*>(this);
    369 }
    370 
    371 ALWAYS_INLINE const JSCell* JSValue::asCell() const
    372 {
    373     ASSERT(!JSImmediate::isImmediate(this));
    374     return static_cast<const JSCell*>(this);
    375 }
    376 
    377 inline bool JSValue::isUndefined() const
    378 {
    379     return this == jsUndefined();
    380 }
    381 
    382 inline bool JSValue::isNull() const
    383 {
    384     return this == jsNull();
    385 }
    386 
    387 inline bool JSValue::isUndefinedOrNull() const
    388 {
    389     return JSImmediate::isUndefinedOrNull(this);
    390 }
    391 
    392 inline bool JSValue::isBoolean() const
    393 {
    394     return JSImmediate::isBoolean(this);
    395 }
    396 
    397 inline bool JSValue::isNumber() const
    398 {
    399     return JSImmediate::isNumber(this) || (!JSImmediate::isImmediate(this) && asCell()->isNumber());
    400 }
    401 
    402 inline bool JSValue::isString() const
    403 {
    404     return !JSImmediate::isImmediate(this) && asCell()->isString();
    405 }
    406 
    407 inline bool JSValue::isObject() const
    408 {
    409     return !JSImmediate::isImmediate(this) && asCell()->isObject();
    410 }
    411 
    412 inline bool JSValue::getBoolean(bool& v) const
    413 {
    414     if (JSImmediate::isBoolean(this)) {
    415         v = JSImmediate::toBoolean(this);
    416         return true;
    417     }
    418    
    419     return false;
    420 }
    421 
    422 inline bool JSValue::getBoolean() const
    423 {
    424     return JSImmediate::isBoolean(this) ? JSImmediate::toBoolean(this) : false;
    425 }
    426 
    427 inline bool JSValue::getNumber(double& v) const
    428 {
    429     if (JSImmediate::isImmediate(this)) {
    430         v = JSImmediate::toDouble(this);
    431         return true;
    432     }
    433     return asCell()->getNumber(v);
    434 }
    435 
    436 inline double JSValue::getNumber() const
    437 {
    438     return JSImmediate::isImmediate(this) ? JSImmediate::toDouble(this) : asCell()->getNumber();
    439 }
     144// --- JSValue inlines ----------------------------
    440145
    441146inline double JSValue::uncheckedGetNumber() const
     
    445150}
    446151
    447 inline bool JSValue::getString(UString& s) const
    448 {
    449     return !JSImmediate::isImmediate(this) && asCell()->getString(s);
    450 }
    451 
    452 inline UString JSValue::getString() const
    453 {
    454     return JSImmediate::isImmediate(this) ? UString() : asCell()->getString();
    455 }
    456 
    457 inline JSObject *JSValue::getObject()
    458 {
    459     return JSImmediate::isImmediate(this) ? 0 : asCell()->getObject();
    460 }
    461 
    462 inline const JSObject *JSValue::getObject() const
    463 {
    464     return JSImmediate::isImmediate(this) ? 0 : asCell()->getObject();
    465 }
    466 
    467 inline CallType JSValue::getCallData(CallData& callData)
    468 {
    469     return JSImmediate::isImmediate(this) ? CallTypeNone : asCell()->getCallData(callData);
    470 }
    471 
    472 inline ConstructType JSValue::getConstructData(ConstructData& constructData)
    473 {
    474     return JSImmediate::isImmediate(this) ? ConstructTypeNone : asCell()->getConstructData(constructData);
    475 }
    476 
    477 ALWAYS_INLINE bool JSValue::getUInt32(uint32_t& v) const
    478 {
    479     return JSImmediate::isImmediate(this) ? JSImmediate::getUInt32(this, v) : asCell()->getUInt32(v);
    480 }
    481 
    482 ALWAYS_INLINE bool JSValue::getTruncatedInt32(int32_t& v) const
    483 {
    484     return JSImmediate::isImmediate(this) ? JSImmediate::getTruncatedInt32(this, v) : asCell()->getTruncatedInt32(v);
    485 }
    486 
    487 inline bool JSValue::getTruncatedUInt32(uint32_t& v) const
    488 {
    489     return JSImmediate::isImmediate(this) ? JSImmediate::getTruncatedUInt32(this, v) : asCell()->getTruncatedUInt32(v);
    490 }
    491 
    492 inline void JSValue::mark()
    493 {
    494     ASSERT(!JSImmediate::isImmediate(this)); // callers should check !marked() before calling mark()
    495     asCell()->mark();
    496 }
    497 
    498 inline bool JSValue::marked() const
    499 {
    500     return JSImmediate::isImmediate(this) || asCell()->marked();
    501 }
    502 
    503 inline JSType JSValue::type() const
    504 {
    505     return JSImmediate::isImmediate(this) ? JSImmediate::type(this) : asCell()->type();
    506 }
    507 
    508 inline JSValue* JSValue::toPrimitive(ExecState* exec, JSType preferredType) const
    509 {
    510     return JSImmediate::isImmediate(this) ? const_cast<JSValue*>(this) : asCell()->toPrimitive(exec, preferredType);
    511 }
    512 
    513 inline bool JSValue::getPrimitiveNumber(ExecState* exec, double& number, JSValue*& value)
    514 {
    515     if (JSImmediate::isImmediate(this)) {
    516         number = JSImmediate::toDouble(this);
    517         value = this;
    518         return true;
    519     }
    520     return asCell()->getPrimitiveNumber(exec, number, value);
    521 }
    522 
    523 inline bool JSValue::toBoolean(ExecState *exec) const
    524 {
    525     return JSImmediate::isImmediate(this) ? JSImmediate::toBoolean(this) : asCell()->toBoolean(exec);
    526 }
    527 
    528 ALWAYS_INLINE double JSValue::toNumber(ExecState *exec) const
    529 {
    530     return JSImmediate::isImmediate(this) ? JSImmediate::toDouble(this) : asCell()->toNumber(exec);
    531 }
    532 
    533152ALWAYS_INLINE JSValue* JSValue::toJSNumber(ExecState* exec) const
    534153{
     
    536155}
    537156
    538 inline UString JSValue::toString(ExecState *exec) const
    539 {
    540     return JSImmediate::isImmediate(this) ? JSImmediate::toString(this) : asCell()->toString(exec);
    541 }
    542 
    543 inline JSObject* JSValue::toObject(ExecState* exec) const
    544 {
    545     return JSImmediate::isImmediate(this) ? JSImmediate::toObject(this, exec) : asCell()->toObject(exec);
    546 }
    547 
    548 ALWAYS_INLINE int32_t JSValue::toInt32(ExecState* exec) const
    549 {
    550     int32_t i;
    551     if (getTruncatedInt32(i))
    552         return i;
    553     bool ok;
    554     return toInt32SlowCase(exec, ok);
    555 }
    556 
    557 inline uint32_t JSValue::toUInt32(ExecState* exec) const
    558 {
    559     uint32_t i;
    560     if (getTruncatedUInt32(i))
    561         return i;
    562     bool ok;
    563     return toUInt32SlowCase(exec, ok);
    564 }
    565 
    566 inline int32_t JSValue::toInt32(double val)
    567 {
    568     if (!(val >= -2147483648.0 && val < 2147483648.0)) {
    569         bool ignored;
    570         return toInt32SlowCase(val, ignored);
    571     }
    572     return static_cast<int32_t>(val);
    573 }
    574 
    575 inline int32_t JSValue::toUInt32(double val)
    576 {
    577     if (!(val >= 0.0 && val < 4294967296.0)) {
    578         bool ignored;
    579         return toUInt32SlowCase(val, ignored);
    580     }
    581     return static_cast<uint32_t>(val);
    582 }
    583 
    584 inline int32_t JSValue::toInt32(ExecState* exec, bool& ok) const
    585 {
    586     int32_t i;
    587     if (getTruncatedInt32(i)) {
    588         ok = true;
    589         return i;
    590     }
    591     return toInt32SlowCase(exec, ok);
    592 }
    593 
    594 inline uint32_t JSValue::toUInt32(ExecState* exec, bool& ok) const
    595 {
    596     uint32_t i;
    597     if (getTruncatedUInt32(i)) {
    598         ok = true;
    599         return i;
    600     }
    601     return toUInt32SlowCase(exec, ok);
    602 }
    603 
    604 inline JSObject* JSValue::toThisObject(ExecState* exec) const
    605 {
    606     if (UNLIKELY(JSImmediate::isImmediate(this)))
    607         return JSImmediate::toObject(this, exec);
    608     return asCell()->toThisObject(exec);
    609 }
    610 
    611 inline UString JSValue::toThisString(ExecState* exec) const
    612 {
    613     return JSImmediate::isImmediate(this) ? JSImmediate::toString(this) : asCell()->toThisString(exec);
    614 }
    615 
    616 inline JSString* JSValue::toThisJSString(ExecState* exec)
    617 {
    618     return JSImmediate::isImmediate(this) ? jsString(exec, JSImmediate::toString(this)) : asCell()->toThisJSString(exec);
    619 }
    620 
    621 inline JSValue* JSValue::getJSNumber()
    622 {
    623     return JSImmediate::isNumber(this) ? this : (JSImmediate::isImmediate(this) ? 0 : asCell()->getJSNumber());
    624 }
     157// -------
    625158
    626159} // namespace KJS
    627160
    628 #endif // JSValue_h
     161#endif // JSNumberCell_h
  • trunk/JavaScriptCore/kjs/JSObject.h

    r34842 r34921  
    2727#include "CommonIdentifiers.h"
    2828#include "ExecState.h"
     29#include "JSNumberCell.h"
    2930#include "JSType.h"
    30 #include "list.h"
    3131#include "PropertyMap.h"
    3232#include "PropertySlot.h"
    3333#include "ScopeChain.h"
     34#include "list.h"
    3435
    3536namespace KJS {
  • trunk/JavaScriptCore/kjs/JSString.cpp

    r34893 r34921  
    125125}
    126126
     127JSString* jsString(ExecState* exec, const char* s)
     128{
     129    return new (exec) JSString(s ? s : "");
     130}
     131
     132JSString* jsString(ExecState* exec, const UString& s)
     133{
     134    return s.isNull() ? new (exec) JSString("") : new (exec) JSString(s);
     135}
     136
     137JSString* jsOwnedString(ExecState* exec, const UString& s)
     138{
     139    return s.isNull() ? new (exec) JSString("", JSString::HasOtherOwner) : new (exec) JSString(s, JSString::HasOtherOwner);
     140}
     141
    127142} // namespace KJS
  • trunk/JavaScriptCore/kjs/JSString.h

    r34893 r34921  
    2626
    2727#include "CommonIdentifiers.h"
    28 #include "JSValue.h"
     28#include "JSCell.h"
    2929#include "PropertySlot.h"
    3030#include "identifier.h"
     
    6969  };
    7070
     71  JSString* jsString(ExecState*, const UString&); // returns empty string if passed null string
     72  JSString* jsString(ExecState*, const char* = ""); // returns empty string if passed 0
     73
     74  // Should be used for strings that are owned by an object that will
     75  // likely outlive the JSValue this makes, such as the parse tree or a
     76  // DOM object that contains a UString
     77  JSString* jsOwnedString(ExecState*, const UString&);
     78
    7179ALWAYS_INLINE bool JSString::getStringPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
    7280{
     
    96104}
    97105
    98 } // namespace
     106// --- JSValue inlines ----------------------------
     107
     108inline JSString* JSValue::toThisJSString(ExecState* exec)
     109{
     110    return JSImmediate::isImmediate(this) ? jsString(exec, JSImmediate::toString(this)) : asCell()->toThisJSString(exec);
     111}
     112
     113} // namespace KJS
    99114
    100115#endif // JSString_h
  • trunk/JavaScriptCore/kjs/JSValue.cpp

    r34878 r34921  
    2525
    2626#include "JSFunction.h"
    27 #include "nodes.h"
    28 #include <stdio.h>
    29 #include <string.h>
    3027#include <wtf/MathExtras.h>
    3128
    3229namespace KJS {
    3330
    34 #if defined NAN && defined INFINITY
    35 
    36 extern const double NaN = NAN;
    37 extern const double Inf = INFINITY;
    38 
    39 #else // !(defined NAN && defined INFINITY)
    40 
    41 // The trick is to define the NaN and Inf globals with a different type than the declaration.
    42 // This trick works because the mangled name of the globals does not include the type, although
    43 // I'm not sure that's guaranteed. There could be alignment issues with this, since arrays of
    44 // characters don't necessarily need the same alignment doubles do, but for now it seems to work.
    45 // It would be good to figure out a 100% clean way that still avoids code that runs at init time.
    46 
    47 // Note, we have to use union to ensure alignment. Otherwise, NaN_Bytes can start anywhere,
    48 // while NaN_double has to be 4-byte aligned for 32-bits.
    49 // With -fstrict-aliasing enabled, unions are the only safe way to do type masquerading.
    50 
    51 static const union {
    52     struct {
    53         unsigned char NaN_Bytes[8];
    54         unsigned char Inf_Bytes[8];
    55     } bytes;
    56    
    57     struct {
    58         double NaN_Double;
    59         double Inf_Double;
    60     } doubles;
    61    
    62 } NaNInf = { {
    63 #if PLATFORM(BIG_ENDIAN)
    64     { 0x7f, 0xf8, 0, 0, 0, 0, 0, 0 },
    65     { 0x7f, 0xf0, 0, 0, 0, 0, 0, 0 }
    66 #elif PLATFORM(MIDDLE_ENDIAN)
    67     { 0, 0, 0xf8, 0x7f, 0, 0, 0, 0 },
    68     { 0, 0, 0xf0, 0x7f, 0, 0, 0, 0 }
    69 #else
    70     { 0, 0, 0, 0, 0, 0, 0xf8, 0x7f },
    71     { 0, 0, 0, 0, 0, 0, 0xf0, 0x7f }
    72 #endif
    73 } } ;
    74 
    75 extern const double NaN = NaNInf.doubles.NaN_Double;
    76 extern const double Inf = NaNInf.doubles.Inf_Double;
    77  
    78 #endif // !(defined NAN && defined INFINITY)
    79 
    80 static const double D16 = 65536.0;
     31static const double D16 = 65536.0; // FIXME: This seems to be unused.
    8132static const double D32 = 4294967296.0;
    82 
    83 void* JSCell::operator new(size_t size, ExecState* exec)
    84 {
    85 #ifdef JAVASCRIPTCORE_BUILDING_ALL_IN_ONE_FILE
    86     return exec->heap()->inlineAllocate(size);
    87 #else
    88     return exec->heap()->allocate(size);
    89 #endif
    90 }
    91 
    92 bool JSCell::getUInt32(uint32_t&) const
    93 {
    94     return false;
    95 }
    96 
    97 bool JSCell::getTruncatedInt32(int32_t&) const
    98 {
    99     return false;
    100 }
    101 
    102 bool JSCell::getTruncatedUInt32(uint32_t&) const
    103 {
    104     return false;
    105 }
    10633
    10734// ECMA 9.4
     
    176103}
    177104
    178 bool JSCell::getNumber(double& numericValue) const
    179 {
    180     if (!isNumber())
    181         return false;
    182     numericValue = static_cast<const JSNumberCell*>(this)->value();
    183     return true;
    184 }
    185 
    186 double JSCell::getNumber() const
    187 {
    188     return isNumber() ? static_cast<const JSNumberCell*>(this)->value() : NaN;
    189 }
    190 
    191 bool JSCell::getString(UString&stringValue) const
    192 {
    193     if (!isString())
    194         return false;
    195     stringValue = static_cast<const JSString*>(this)->value();
    196     return true;
    197 }
    198 
    199 UString JSCell::getString() const
    200 {
    201     return isString() ? static_cast<const JSString*>(this)->value() : UString();
    202 }
    203 
    204 JSObject* JSCell::getObject()
    205 {
    206     return isObject() ? static_cast<JSObject*>(this) : 0;
    207 }
    208 
    209 const JSObject* JSCell::getObject() const
    210 {
    211     return isObject() ? static_cast<const JSObject*>(this) : 0;
    212 }
    213 
    214 CallType JSCell::getCallData(CallData&)
    215 {
    216     return CallTypeNone;
    217 }
    218 
    219 ConstructType JSCell::getConstructData(ConstructData&)
    220 {
    221     return ConstructTypeNone;
    222 }
    223 
    224 bool JSCell::getOwnPropertySlot(ExecState* exec, const Identifier& identifier, PropertySlot& slot)
    225 {
    226     // This is not a general purpose implementation of getOwnPropertySlot.
    227     // It should only be called by JSValue::get.
    228     // It calls getPropertySlot, not getOwnPropertySlot.
    229     JSObject* object = toObject(exec);
    230     slot.setBase(object);
    231     if (!object->getPropertySlot(exec, identifier, slot))
    232         slot.setUndefined();
    233     return true;
    234 }
    235 
    236 bool JSCell::getOwnPropertySlot(ExecState* exec, unsigned identifier, PropertySlot& slot)
    237 {
    238     // This is not a general purpose implementation of getOwnPropertySlot.
    239     // It should only be called by JSValue::get.
    240     // It calls getPropertySlot, not getOwnPropertySlot.
    241     JSObject* object = toObject(exec);
    242     slot.setBase(object);
    243     if (!object->getPropertySlot(exec, identifier, slot))
    244         slot.setUndefined();
    245     return true;
    246 }
    247 
    248 void JSCell::put(ExecState* exec, const Identifier& identifier, JSValue* value)
    249 {
    250     toObject(exec)->put(exec, identifier, value);
    251 }
    252 
    253 void JSCell::put(ExecState* exec, unsigned identifier, JSValue* value)
    254 {
    255     toObject(exec)->put(exec, identifier, value);
    256 }
    257 
    258 bool JSCell::deleteProperty(ExecState* exec, const Identifier& identifier)
    259 {
    260     return toObject(exec)->deleteProperty(exec, identifier);
    261 }
    262 
    263 bool JSCell::deleteProperty(ExecState* exec, unsigned identifier)
    264 {
    265     return toObject(exec)->deleteProperty(exec, identifier);
    266 }
    267 
    268 JSObject* JSCell::toThisObject(ExecState* exec) const
    269 {
    270     return toObject(exec);
    271 }
    272 
    273 UString JSCell::toThisString(ExecState* exec) const
    274 {
    275     return toThisObject(exec)->toString(exec);
    276 }
    277 
    278 JSString* JSCell::toThisJSString(ExecState* exec)
    279 {
    280     return jsString(exec, toThisString(exec));
    281 }
    282 
    283 const ClassInfo* JSCell::classInfo() const
    284 {
    285     return 0;
    286 }
    287 
    288 JSValue* JSCell::getJSNumber()
    289 {
    290     return 0;
    291 }
    292 
    293 JSString* jsString(ExecState* exec, const char* s)
    294 {
    295     return new (exec) JSString(s ? s : "");
    296 }
    297 
    298 JSString* jsString(ExecState* exec, const UString& s)
    299 {
    300     return s.isNull() ? new (exec) JSString("") : new (exec) JSString(s);
    301 }
    302 
    303 JSString* jsOwnedString(ExecState* exec, const UString& s)
    304 {
    305     return s.isNull() ? new (exec) JSString("", JSString::HasOtherOwner) : new (exec) JSString(s, JSString::HasOtherOwner);
    306 }
    307 
     105// Declared in CallData.h
    308106JSValue* call(ExecState* exec, JSValue* functionObject, CallType callType, const CallData& callData, JSValue* thisValue, const ArgList& args)
    309107{
     
    315113}
    316114
     115// Declared in ConstructData.h
    317116JSObject* construct(ExecState* exec, JSValue* object, ConstructType constructType, const ConstructData& constructData, const ArgList& args)
    318117{
  • trunk/JavaScriptCore/kjs/JSValue.h

    r34821 r34921  
    2828#include "ExecState.h"
    2929#include "JSImmediate.h"
    30 #include "collector.h"
    3130#include "ustring.h"
    3231#include <stddef.h> // for size_t
     
    4039class JSString;
    4140class PropertySlot;
    42 
    4341struct ClassInfo;
    4442struct Instruction;
     
    150148};
    151149
    152 class JSCell : public JSValue {
    153     friend class Heap;
    154     friend class GetterSetter;
    155     friend class JSObject;
    156     friend class JSPropertyNameIterator;
    157     friend class JSValue;
    158     friend class JSNumberCell;
    159     friend class JSString;
    160 private:
    161     JSCell();
    162     virtual ~JSCell();
    163 
    164 public:
    165     // Querying the type.
    166     virtual JSType type() const = 0;
    167     bool isNumber() const;
    168     bool isString() const;
    169     bool isObject() const;
    170     bool isObject(const ClassInfo*) const; // FIXME: Merge with inherits.
    171 
    172     // Extracting the value.
    173     bool getNumber(double&) const;
    174     double getNumber() const; // NaN if not a number
    175     bool getString(UString&) const;
    176     UString getString() const; // null string if not a string
    177     JSObject* getObject(); // NULL if not an object
    178     const JSObject* getObject() const; // NULL if not an object
    179    
    180     virtual CallType getCallData(CallData&);
    181     virtual ConstructType getConstructData(ConstructData&);
    182 
    183     // Extracting integer values.
    184     virtual bool getUInt32(uint32_t&) const;
    185     virtual bool getTruncatedInt32(int32_t&) const;
    186     virtual bool getTruncatedUInt32(uint32_t&) const;
    187 
    188     // Basic conversions.
    189     virtual JSValue* toPrimitive(ExecState*, JSType preferredType = UnspecifiedType) const = 0;
    190     virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue*&) = 0;
    191     virtual bool toBoolean(ExecState*) const = 0;
    192     virtual double toNumber(ExecState*) const = 0;
    193     virtual UString toString(ExecState*) const = 0;
    194     virtual JSObject* toObject(ExecState*) const = 0;
    195 
    196     // Garbage collection.
    197     void* operator new(size_t, ExecState*);
    198     virtual void mark();
    199     bool marked() const;
    200 
    201     // Object operations, with the toObject operation included.
    202     virtual const ClassInfo* classInfo() const;
    203     virtual void put(ExecState*, const Identifier& propertyName, JSValue*);
    204     virtual void put(ExecState*, unsigned propertyName, JSValue*);
    205     virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
    206     virtual bool deleteProperty(ExecState*, unsigned propertyName);
    207 
    208     virtual JSObject* toThisObject(ExecState*) const;
    209     virtual UString toThisString(ExecState*) const;
    210     virtual JSString* toThisJSString(ExecState*);
    211     virtual JSValue* getJSNumber();
    212 
    213 private:
    214     // Base implementation, but for non-object classes implements getPropertySlot.
    215     virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
    216     virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
    217 };
    218 
    219 class JSNumberCell : public JSCell {
    220     friend JSValue* jsNumberCell(ExecState*, double);
    221 public:
    222     double value() const { return val; }
    223 
    224     virtual JSType type() const;
    225 
    226     virtual JSValue* toPrimitive(ExecState*, JSType preferred = UnspecifiedType) const;
    227     virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue*& value);
    228     virtual bool toBoolean(ExecState*) const;
    229     virtual double toNumber(ExecState*) const;
    230     virtual UString toString(ExecState*) const;
    231     virtual JSObject* toObject(ExecState*) const;
    232 
    233     virtual UString toThisString(ExecState*) const;
    234     virtual JSObject* toThisObject(ExecState*) const;
    235     virtual JSValue* getJSNumber();
    236 
    237     void* operator new(size_t size, ExecState* exec)
    238     {
    239 #ifdef JAVASCRIPTCORE_BUILDING_ALL_IN_ONE_FILE
    240         return exec->heap()->inlineAllocateNumber(size);
    241 #else
    242         return exec->heap()->allocateNumber(size);
    243 #endif
    244     }
    245 
    246 private:
    247     JSNumberCell(double v)
    248         : val(v)
    249     {
    250     }
    251 
    252     virtual bool getUInt32(uint32_t&) const;
    253     virtual bool getTruncatedInt32(int32_t&) const;
    254     virtual bool getTruncatedUInt32(uint32_t&) const;
    255 
    256     double val;
    257 };
    258 
    259 JSString* jsString(ExecState*, const UString&); // returns empty string if passed null string
    260 JSString* jsString(ExecState*, const char* = ""); // returns empty string if passed 0
    261 
    262 // should be used for strings that are owned by an object that will
    263 // likely outlive the JSValue this makes, such as the parse tree or a
    264 // DOM object that contains a UString
    265 JSString* jsOwnedString(ExecState*, const UString&);
    266 
    267 extern const double NaN;
    268 extern const double Inf;
    269 
    270 // Beware marking this function ALWAYS_INLINE: It takes a PIC branch, so
    271 // inlining it may not always be a win.
    272 inline JSValue* jsNumberCell(ExecState* exec, double d)
    273 {
    274     return new (exec) JSNumberCell(d);
    275 }
    276 
    277 inline JSValue* jsNaN(ExecState* exec)
    278 {
    279     return jsNumberCell(exec, NaN);
    280 }
    281 
    282 ALWAYS_INLINE JSValue* jsNumber(ExecState* exec, double d)
    283 {
    284     JSValue* v = JSImmediate::from(d);
    285     return v ? v : jsNumberCell(exec, d);
    286 }
    287 
    288 ALWAYS_INLINE JSValue* jsNumber(ExecState* exec, int i)
    289 {
    290     JSValue* v = JSImmediate::from(i);
    291     return v ? v : jsNumberCell(exec, i);
    292 }
    293 
    294 ALWAYS_INLINE JSValue* jsNumber(ExecState* exec, unsigned i)
    295 {
    296     JSValue* v = JSImmediate::from(i);
    297     return v ? v : jsNumberCell(exec, i);
    298 }
    299 
    300 ALWAYS_INLINE JSValue* jsNumber(ExecState* exec, long i)
    301 {
    302     JSValue* v = JSImmediate::from(i);
    303     return v ? v : jsNumberCell(exec, i);
    304 }
    305 
    306 ALWAYS_INLINE JSValue* jsNumber(ExecState* exec, unsigned long i)
    307 {
    308     JSValue* v = JSImmediate::from(i);
    309     return v ? v : jsNumberCell(exec, i);
    310 }
    311 
    312 ALWAYS_INLINE JSValue* jsNumber(ExecState* exec, long long i)
    313 {
    314     JSValue* v = JSImmediate::from(i);
    315     return v ? v : jsNumberCell(exec, static_cast<double>(i));
    316 }
    317 
    318 ALWAYS_INLINE JSValue* jsNumber(ExecState* exec, unsigned long long i)
    319 {
    320     JSValue* v = JSImmediate::from(i);
    321     return v ? v : jsNumberCell(exec, static_cast<double>(i));
    322 }
    323 
    324150inline JSValue::JSValue()
    325151{
     
    330156}
    331157
    332 inline JSCell::JSCell()
    333 {
    334 }
    335 
    336 inline JSCell::~JSCell()
    337 {
    338 }
    339 
    340 inline bool JSCell::isNumber() const
    341 {
    342     return type() == NumberType;
    343 }
    344 
    345 inline bool JSCell::isString() const
    346 {
    347     return type() == StringType;
    348 }
    349 
    350 inline bool JSCell::isObject() const
    351 {
    352     return type() == ObjectType;
    353 }
    354 
    355 inline bool JSCell::marked() const
    356 {
    357     return Heap::isCellMarked(this);
    358 }
    359 
    360 inline void JSCell::mark()
    361 {
    362     return Heap::markCell(this);
    363 }
    364 
    365 ALWAYS_INLINE JSCell* JSValue::asCell()
    366 {
    367     ASSERT(!JSImmediate::isImmediate(this));
    368     return static_cast<JSCell*>(this);
    369 }
    370 
    371 ALWAYS_INLINE const JSCell* JSValue::asCell() const
    372 {
    373     ASSERT(!JSImmediate::isImmediate(this));
    374     return static_cast<const JSCell*>(this);
    375 }
    376 
    377158inline bool JSValue::isUndefined() const
    378159{
     
    393174{
    394175    return JSImmediate::isBoolean(this);
    395 }
    396 
    397 inline bool JSValue::isNumber() const
    398 {
    399     return JSImmediate::isNumber(this) || (!JSImmediate::isImmediate(this) && asCell()->isNumber());
    400 }
    401 
    402 inline bool JSValue::isString() const
    403 {
    404     return !JSImmediate::isImmediate(this) && asCell()->isString();
    405 }
    406 
    407 inline bool JSValue::isObject() const
    408 {
    409     return !JSImmediate::isImmediate(this) && asCell()->isObject();
    410176}
    411177
     
    425191}
    426192
    427 inline bool JSValue::getNumber(double& v) const
    428 {
    429     if (JSImmediate::isImmediate(this)) {
    430         v = JSImmediate::toDouble(this);
    431         return true;
    432     }
    433     return asCell()->getNumber(v);
    434 }
    435 
    436 inline double JSValue::getNumber() const
    437 {
    438     return JSImmediate::isImmediate(this) ? JSImmediate::toDouble(this) : asCell()->getNumber();
    439 }
    440 
    441 inline double JSValue::uncheckedGetNumber() const
    442 {
    443     ASSERT(JSImmediate::isImmediate(this) || asCell()->isNumber());
    444     return JSImmediate::isImmediate(this) ? JSImmediate::toDouble(this) : static_cast<const JSNumberCell*>(this)->value();
    445 }
    446 
    447 inline bool JSValue::getString(UString& s) const
    448 {
    449     return !JSImmediate::isImmediate(this) && asCell()->getString(s);
    450 }
    451 
    452 inline UString JSValue::getString() const
    453 {
    454     return JSImmediate::isImmediate(this) ? UString() : asCell()->getString();
    455 }
    456 
    457 inline JSObject *JSValue::getObject()
    458 {
    459     return JSImmediate::isImmediate(this) ? 0 : asCell()->getObject();
    460 }
    461 
    462 inline const JSObject *JSValue::getObject() const
    463 {
    464     return JSImmediate::isImmediate(this) ? 0 : asCell()->getObject();
    465 }
    466 
    467 inline CallType JSValue::getCallData(CallData& callData)
    468 {
    469     return JSImmediate::isImmediate(this) ? CallTypeNone : asCell()->getCallData(callData);
    470 }
    471 
    472 inline ConstructType JSValue::getConstructData(ConstructData& constructData)
    473 {
    474     return JSImmediate::isImmediate(this) ? ConstructTypeNone : asCell()->getConstructData(constructData);
    475 }
    476 
    477 ALWAYS_INLINE bool JSValue::getUInt32(uint32_t& v) const
    478 {
    479     return JSImmediate::isImmediate(this) ? JSImmediate::getUInt32(this, v) : asCell()->getUInt32(v);
    480 }
    481 
    482 ALWAYS_INLINE bool JSValue::getTruncatedInt32(int32_t& v) const
    483 {
    484     return JSImmediate::isImmediate(this) ? JSImmediate::getTruncatedInt32(this, v) : asCell()->getTruncatedInt32(v);
    485 }
    486 
    487 inline bool JSValue::getTruncatedUInt32(uint32_t& v) const
    488 {
    489     return JSImmediate::isImmediate(this) ? JSImmediate::getTruncatedUInt32(this, v) : asCell()->getTruncatedUInt32(v);
    490 }
    491 
    492 inline void JSValue::mark()
    493 {
    494     ASSERT(!JSImmediate::isImmediate(this)); // callers should check !marked() before calling mark()
    495     asCell()->mark();
    496 }
    497 
    498 inline bool JSValue::marked() const
    499 {
    500     return JSImmediate::isImmediate(this) || asCell()->marked();
    501 }
    502 
    503 inline JSType JSValue::type() const
    504 {
    505     return JSImmediate::isImmediate(this) ? JSImmediate::type(this) : asCell()->type();
    506 }
    507 
    508 inline JSValue* JSValue::toPrimitive(ExecState* exec, JSType preferredType) const
    509 {
    510     return JSImmediate::isImmediate(this) ? const_cast<JSValue*>(this) : asCell()->toPrimitive(exec, preferredType);
    511 }
    512 
    513 inline bool JSValue::getPrimitiveNumber(ExecState* exec, double& number, JSValue*& value)
    514 {
    515     if (JSImmediate::isImmediate(this)) {
    516         number = JSImmediate::toDouble(this);
    517         value = this;
    518         return true;
    519     }
    520     return asCell()->getPrimitiveNumber(exec, number, value);
    521 }
    522 
    523 inline bool JSValue::toBoolean(ExecState *exec) const
    524 {
    525     return JSImmediate::isImmediate(this) ? JSImmediate::toBoolean(this) : asCell()->toBoolean(exec);
    526 }
    527 
    528 ALWAYS_INLINE double JSValue::toNumber(ExecState *exec) const
    529 {
    530     return JSImmediate::isImmediate(this) ? JSImmediate::toDouble(this) : asCell()->toNumber(exec);
    531 }
    532 
    533 ALWAYS_INLINE JSValue* JSValue::toJSNumber(ExecState* exec) const
    534 {
    535     return JSImmediate::isNumber(this) ? const_cast<JSValue*>(this) : jsNumber(exec, this->toNumber(exec));
    536 }
    537 
    538 inline UString JSValue::toString(ExecState *exec) const
    539 {
    540     return JSImmediate::isImmediate(this) ? JSImmediate::toString(this) : asCell()->toString(exec);
    541 }
    542 
    543 inline JSObject* JSValue::toObject(ExecState* exec) const
    544 {
    545     return JSImmediate::isImmediate(this) ? JSImmediate::toObject(this, exec) : asCell()->toObject(exec);
    546 }
    547 
    548193ALWAYS_INLINE int32_t JSValue::toInt32(ExecState* exec) const
    549194{
     
    602247}
    603248
    604 inline JSObject* JSValue::toThisObject(ExecState* exec) const
    605 {
    606     if (UNLIKELY(JSImmediate::isImmediate(this)))
    607         return JSImmediate::toObject(this, exec);
    608     return asCell()->toThisObject(exec);
    609 }
    610 
    611 inline UString JSValue::toThisString(ExecState* exec) const
    612 {
    613     return JSImmediate::isImmediate(this) ? JSImmediate::toString(this) : asCell()->toThisString(exec);
    614 }
    615 
    616 inline JSString* JSValue::toThisJSString(ExecState* exec)
    617 {
    618     return JSImmediate::isImmediate(this) ? jsString(exec, JSImmediate::toString(this)) : asCell()->toThisJSString(exec);
    619 }
    620 
    621 inline JSValue* JSValue::getJSNumber()
    622 {
    623     return JSImmediate::isNumber(this) ? this : (JSImmediate::isImmediate(this) ? 0 : asCell()->getJSNumber());
    624 }
    625 
    626249} // namespace KJS
    627250
Note: See TracChangeset for help on using the changeset viewer.