Reviewed by Oliver.
authordarin@apple.com <darin@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 9 Nov 2007 05:48:49 +0000 (05:48 +0000)
committerdarin@apple.com <darin@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 9 Nov 2007 05:48:49 +0000 (05:48 +0000)
        - http://bugs.webkit.org/show_bug.cgi?id=15904
          more speed-ups possible by tightening up int version of JSImmediate

        1% improvement of SunSpider

        * kjs/JSImmediate.h: Eliminate the now-unneeded FPBitValues struct template.
        (KJS::JSImmediate::from): Overload for most numeric types; many types can
        do fewer branches and checks.
        (KJS::JSImmediate::getUInt32): Removed unneeded check for undefined.
        (KJS::JSImmediate::getTruncatedInt32): Ditto.
        (KJS::JSImmediate::getTruncatedUInt32): Ditto. There's no difference any more
        between getUInt32 and getTruncatedUInt32, so that's worth a rename and merge later.

        * kjs/grammar.y: Update since fromDouble is now just from.
        * kjs/nodes.h: Ditto.

        * kjs/value.h: (KJS::jsNumber): Overload for most numeric types.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@27632 268f45cc-cd09-0410-ab3c-d52691b4dbfc

JavaScriptCore/ChangeLog
JavaScriptCore/kjs/JSImmediate.h
JavaScriptCore/kjs/grammar.y
JavaScriptCore/kjs/nodes.cpp
JavaScriptCore/kjs/nodes.h
JavaScriptCore/kjs/value.h

index d72af61b4152c15b57e0f5b967464211da83a314..affbbc3158aa6b3d5af8d34cffcc620c4ae10a59 100644 (file)
@@ -1,3 +1,25 @@
+2007-11-08  Darin Adler  <darin@apple.com>
+
+        Reviewed by Oliver.
+
+        - http://bugs.webkit.org/show_bug.cgi?id=15904
+          more speed-ups possible by tightening up int version of JSImmediate
+
+        1% improvement of SunSpider
+
+        * kjs/JSImmediate.h: Eliminate the now-unneeded FPBitValues struct template.
+        (KJS::JSImmediate::from): Overload for most numeric types; many types can
+        do fewer branches and checks.
+        (KJS::JSImmediate::getUInt32): Removed unneeded check for undefined.
+        (KJS::JSImmediate::getTruncatedInt32): Ditto.
+        (KJS::JSImmediate::getTruncatedUInt32): Ditto. There's no difference any more
+        between getUInt32 and getTruncatedUInt32, so that's worth a rename and merge later.
+
+        * kjs/grammar.y: Update since fromDouble is now just from.
+        * kjs/nodes.h: Ditto.
+
+        * kjs/value.h: (KJS::jsNumber): Overload for most numeric types.
+
 2007-11-08  Kevin Ollivier  <kevino@theolliviers.com>
 
         Bakefiles for building JavaScriptCore, needed by wx port.
index 59998d9d4313a275aa3e2a31d56fa0c1b45f08d4..a71cb625422c93d87a5d49d0f3873a1262ec0596 100644 (file)
@@ -82,6 +82,19 @@ public:
         return (getTag(v) == UndefinedType);
     }
 
+    static JSValue* from(char);
+    static JSValue* from(signed char);
+    static JSValue* from(unsigned char);
+    static JSValue* from(short);
+    static JSValue* from(unsigned short);
+    static JSValue* from(int);
+    static JSValue* from(unsigned);
+    static JSValue* from(long);
+    static JSValue* from(unsigned long);
+    static JSValue* from(long long);
+    static JSValue* from(unsigned long long);
+    static JSValue* from(double);
+
     static ALWAYS_INLINE bool areBothImmediateNumbers(const JSValue* v1, const JSValue* v2)
     {
         return (reinterpret_cast<uintptr_t>(v1) & reinterpret_cast<uintptr_t>(v2) & TagMask) == NumberType;
@@ -93,7 +106,6 @@ public:
         return reinterpret_cast<JSValue*>(reinterpret_cast<uintptr_t>(v1) & reinterpret_cast<uintptr_t>(v2));
     }
 
-    static JSValue* fromDouble(double d);
     static double toDouble(const JSValue*);
     static bool toBoolean(const JSValue*);
     static JSObject* toObject(const JSValue*, ExecState*);
@@ -104,8 +116,6 @@ public:
     static bool getTruncatedInt32(const JSValue*, int32_t&);
     static bool getTruncatedUInt32(const JSValue*, uint32_t&);
 
-    // It would nice just to use fromDouble() to create these values, but that would prevent them from
-    // turning into compile-time constants.
     static JSValue* trueImmediate();
     static JSValue* falseImmediate();
     static JSValue* undefinedImmediate();
@@ -113,6 +123,11 @@ public:
     
 private:
     static const uintptr_t TagMask = 3; // type tags are 2 bits long
+
+    // Immediate values are restricted to a 30 bit signed value.
+    static const int minImmediateInt = -(1 << 29);
+    static const int maxImmediateInt = (1 << 29) - 1;
+    static const unsigned maxImmediateUInt = maxImmediateInt;
     
     static ALWAYS_INLINE JSValue* tag(uintptr_t bits, uintptr_t tag)
     {
@@ -128,146 +143,126 @@ private:
     {
         return reinterpret_cast<uintptr_t>(v) & TagMask;
     }
-    
-    // we support 32-bit platforms with sizes like this
-    static const bool is32bit = 
-        sizeof(float) == sizeof(uint32_t) && sizeof(double) == sizeof(uint64_t) && sizeof(uintptr_t) == sizeof(uint32_t);
+};
 
-    // we support 64-bit platforms with sizes like this
-    static const bool is64bit =
-        sizeof(float) == sizeof(uint32_t) && sizeof(double) == sizeof(uint64_t) && sizeof(uintptr_t) == sizeof(uint64_t);
+ALWAYS_INLINE JSValue* JSImmediate::trueImmediate() { return tag(1 << 2, BooleanType); }
+ALWAYS_INLINE JSValue* JSImmediate::falseImmediate() { return tag(0, BooleanType); }
+ALWAYS_INLINE JSValue* JSImmediate::undefinedImmediate() { return tag(1 << 2, UndefinedType); }
+ALWAYS_INLINE JSValue* JSImmediate::nullImmediate() { return tag(0, UndefinedType); }
 
-    template<bool for32bit, bool for64bit> struct FPBitValues {};
-};
+ALWAYS_INLINE bool JSImmediate::toBoolean(const JSValue* v)
+{
+    ASSERT(isImmediate(v));
+    uintptr_t bits = unTag(v);
+    return (bits != 0) & (JSImmediate::getTag(v) != UndefinedType);
+}
 
-template<> struct JSImmediate::FPBitValues<true, false> {
-    static const uint32_t nanAsBits = 0x7fc00000;
-    static const uint32_t oneAsBits = 0x3f800000;
-    static const uint32_t zeroAsBits = 0x0;
+ALWAYS_INLINE JSValue* JSImmediate::from(char i)
+{
+    return tag(i << 2, NumberType);
+}
 
-    static ALWAYS_INLINE JSValue* fromDouble(double d)
-    {
-        const int32_t intVal = static_cast<int>(d);
-        
-        // On 32 bit systems immediate values are restricted to a 30 bit signed value
-        if ((intVal <= -(1 << 29)) | (intVal >= ((1 << 29) - 1)))
-            return 0;
-        
-        // Check for data loss from conversion to int. This
-        // will reject NaN, +/-Inf, and -0.
-        // Happily none of these are as common as raw int values
-        if ((intVal != d) || (signbit(d) && !intVal))
-            return 0;
-        
-        return tag(intVal << 2, NumberType);
-    }
+ALWAYS_INLINE JSValue* JSImmediate::from(signed char i)
+{
+    return tag(i << 2, NumberType);
+}
 
-    static ALWAYS_INLINE double toDouble(const JSValue* v)
-    {
-        ASSERT(isImmediate(v));
-        const int32_t i = static_cast<int32_t>(unTag(v)) >> 2;
-        if (JSImmediate::getTag(v) == UndefinedType && i)
-            return std::numeric_limits<double>::quiet_NaN();
-        return i;
-    }
-    
-    static ALWAYS_INLINE bool getTruncatedInt32(const JSValue* v, int32_t& i)
-    {
-        i = static_cast<int32_t>(unTag(v)) >> 2;
-        if (JSImmediate::getTag(v) == UndefinedType && i)
-            return false;
-        return isNumber(v);
-    }
-    
-    static ALWAYS_INLINE bool getTruncatedUInt32(const JSValue* v, uint32_t& i)
-    {
-        int32_t& si = reinterpret_cast<int&>(i);
-        return getTruncatedInt32(v, si) & (si >= 0);
-    }
-};
+ALWAYS_INLINE JSValue* JSImmediate::from(unsigned char i)
+{
+    return tag(i << 2, NumberType);
+}
 
-template<> struct JSImmediate::FPBitValues<false, true> {
-    static const uint64_t nanAsBits = 0x7ff80000ULL << 32;
-    static const uint64_t oneAsBits = 0x3ff00000ULL << 32;
-    static const uint64_t zeroAsBits = 0x0;
+ALWAYS_INLINE JSValue* JSImmediate::from(short i)
+{
+    return tag(i << 2, NumberType);
+}
 
-    static ALWAYS_INLINE JSValue* fromDouble(double d)
-    {
-        const int64_t intVal = static_cast<int>(d);
-        
-        // Technically we could fit a 60 bit signed int here, however that would
-        // required more branches when extracting int values.
-        if ((intVal <= -(1L << 29)) | (intVal >= ((1 << 29) - 1)))
-            return 0;
-        
-        // Check for data loss from conversion to int. This
-        // will reject NaN, +/-Inf, and -0.
-        // Happily none of these are as common as raw int values
-        if ((intVal != d) || (signbit(d) && !intVal))
-            return 0;
-
-        return tag(static_cast<uintptr_t>(intVal << 2), NumberType);
-    }
+ALWAYS_INLINE JSValue* JSImmediate::from(unsigned short i)
+{
+    return tag(i << 2, NumberType);
+}
 
-    static ALWAYS_INLINE double toDouble(const JSValue* v)
-    {
-        ASSERT(isImmediate(v));
-        const int32_t i = static_cast<int32_t>(unTag(v) >> 2);
-        if (JSImmediate::getTag(v) == UndefinedType && i)
-            return std::numeric_limits<double>::quiet_NaN();
-        return i;
-    }
+ALWAYS_INLINE JSValue* JSImmediate::from(int i)
+{
+    if ((i < minImmediateInt) | (i > maxImmediateInt))
+        return 0;
+    return tag(i << 2, NumberType);
+}
 
-    static ALWAYS_INLINE bool getTruncatedInt32(const JSValue* v, int32_t& i)
-    {
-        i = static_cast<int32_t>(unTag(v) >> 2);
-        if (JSImmediate::getTag(v) == UndefinedType && i)
-            return false;
-        return isNumber(v);
-    }
+ALWAYS_INLINE JSValue* JSImmediate::from(unsigned i)
+{
+    if (i > maxImmediateUInt)
+        return 0;
+    return tag(i << 2, NumberType);
+}
 
-    static ALWAYS_INLINE bool getTruncatedUInt32(const JSValue* v, uint32_t& i)
-    {      
-        int& si = reinterpret_cast<int&>(i);
-        return getTruncatedInt32(v, si) & (si >= 0);
-    }
-};
+ALWAYS_INLINE JSValue* JSImmediate::from(long i)
+{
+    if ((i < minImmediateInt) | (i > maxImmediateInt))
+        return 0;
+    return tag(i << 2, NumberType);
+}
 
-ALWAYS_INLINE JSValue* JSImmediate::trueImmediate() { return tag(1 << 2, BooleanType); }
-ALWAYS_INLINE JSValue* JSImmediate::falseImmediate() { return tag(0, BooleanType); }
-ALWAYS_INLINE JSValue* JSImmediate::undefinedImmediate() { return tag(1 << 2, UndefinedType); }
-ALWAYS_INLINE JSValue* JSImmediate::nullImmediate() { return tag(0, UndefinedType); }
+ALWAYS_INLINE JSValue* JSImmediate::from(unsigned long i)
+{
+    if (i > maxImmediateUInt)
+        return 0;
+    return tag(i << 2, NumberType);
+}
 
-ALWAYS_INLINE bool JSImmediate::toBoolean(const JSValue* v)
+ALWAYS_INLINE JSValue* JSImmediate::from(long long i)
 {
-    ASSERT(isImmediate(v));
-    uintptr_t bits = unTag(v);
-    return (bits != 0) & (JSImmediate::getTag(v) != UndefinedType);
+    if ((i < minImmediateInt) | (i > maxImmediateInt))
+        return 0;
+    return tag(static_cast<uintptr_t>(i) << 2, NumberType);
+}
+
+ALWAYS_INLINE JSValue* JSImmediate::from(unsigned long long i)
+{
+    if (i > maxImmediateUInt)
+        return 0;
+    return tag(static_cast<uintptr_t>(i) << 2, NumberType);
 }
 
-ALWAYS_INLINE JSValue* JSImmediate::fromDouble(double d)
+ALWAYS_INLINE JSValue* JSImmediate::from(double d)
 {
-    return FPBitValues<is32bit, is64bit>::fromDouble(d);
+    const int intVal = static_cast<int>(d);
+
+    if ((intVal < minImmediateInt) | (intVal > maxImmediateInt))
+        return 0;
+
+    // Check for data loss from conversion to int.
+    if ((intVal != d) || (signbit(d) && !intVal))
+        return 0;
+
+    return tag(intVal << 2, NumberType);
 }
 
 ALWAYS_INLINE double JSImmediate::toDouble(const JSValue* v)
 {
-    return FPBitValues<is32bit, is64bit>::toDouble(v);
+    ASSERT(isImmediate(v));
+    const int32_t i = static_cast<int32_t>(unTag(v)) >> 2;
+    if (JSImmediate::getTag(v) == UndefinedType && i)
+        return std::numeric_limits<double>::quiet_NaN();
+    return i;
 }
 
 ALWAYS_INLINE bool JSImmediate::getUInt32(const JSValue* v, uint32_t& i)
 {
-    return FPBitValues<is32bit, is64bit>::getTruncatedUInt32(v, i);
+    const int32_t si = static_cast<int32_t>(unTag(v)) >> 2;
+    i = si;
+    return isNumber(v) & (si >= 0);
 }
 
 ALWAYS_INLINE bool JSImmediate::getTruncatedInt32(const JSValue* v, int32_t& i)
 {
-    return FPBitValues<is32bit, is64bit>::getTruncatedInt32(v, i);
+    i = static_cast<int32_t>(unTag(v)) >> 2;
+    return isNumber(v);
 }
 
 ALWAYS_INLINE bool JSImmediate::getTruncatedUInt32(const JSValue* v, uint32_t& i)
 {
-    return FPBitValues<is32bit, is64bit>::getTruncatedUInt32(v, i);
+    return getUInt32(v, i);
 }
 
 } // namespace KJS
index f5f2c58943541fc49101858e146d77fffef33087..0e2f658408a7700cacd30e9f254d8819a8ab638f 100644 (file)
@@ -206,9 +206,9 @@ static NumberNode* makeNumberNode(double);
 %%
 
 Literal:
-    NULLTOKEN                           { $$ = new NullNode(); }
-  | TRUETOKEN                           { $$ = new BooleanNode(true); }
-  | FALSETOKEN                          { $$ = new BooleanNode(false); }
+    NULLTOKEN                           { $$ = new NullNode; }
+  | TRUETOKEN                           { $$ = new TrueNode; }
+  | FALSETOKEN                          { $$ = new FalseNode; }
   | NUMBER                              { $$ = makeNumberNode($1); }
   | STRING                              { $$ = new StringNode($1); }
   | '/' /* regexp */                    {
@@ -1037,7 +1037,7 @@ static ExpressionNode* makeNegateNode(ExpressionNode* n)
 
 static NumberNode* makeNumberNode(double d)
 {
-    JSValue* value = JSImmediate::fromDouble(d);
+    JSValue* value = JSImmediate::from(d);
     if (value)
         return new ImmediateNumberNode(value, d);
     return new NumberNode(d);
index b2a03fe85834deab9137ed4ba09903e3f2cf60e9..2858208eeffef8e1250c4c6de209cff7741dd599 100644 (file)
@@ -655,12 +655,6 @@ void ArgumentListNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStac
     nodeStack.append(expr.get());
 }
 
-JSValue *ArgumentListNode::evaluate(ExecState *)
-{
-  ASSERT(0);
-  return 0; // dummy, see evaluateList()
-}
-
 // ECMA 11.2.4
 void ArgumentListNode::evaluateList(ExecState* exec, List& list)
 {
@@ -679,12 +673,6 @@ void ArgumentsNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks:
         nodeStack.append(listNode.get());
 }
 
-JSValue *ArgumentsNode::evaluate(ExecState *)
-{
-  ASSERT(0);
-  return 0; // dummy, see evaluateList()
-}
-
 // ------------------------------ NewExprNode ----------------------------------
 
 void NewExprNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
index 7add7229d6cf4bd28d9d1677e9cda47c6793dd85..c165e89e107a3cd79936409ab719df1418f2bbc2 100644 (file)
@@ -1,4 +1,3 @@
-// -*- c-basic-offset: 2 -*-
 /*
  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
@@ -111,7 +110,7 @@ namespace KJS {
       FunctionStack& functionStack;
   };
 
-  class Node {
+  class Node : Noncopyable {
   public:
     Node() KJS_FAST_CALL;
     Node(PlacementNewAdoptType) KJS_FAST_CALL { }
@@ -135,9 +134,6 @@ namespace KJS {
     // Used for iterative, depth-first traversal of the node tree. Does not cross function call boundaries.
     virtual void optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack&) KJS_FAST_CALL { }
 
-    // Used to optimize those nodes that do extra work when returning a result, even if the result has no semantic relevance
-    virtual void optimizeForUnnecessaryResult() { }
-      
   protected:
     Completion createErrorCompletion(ExecState *, ErrorType, const char *msg) KJS_FAST_CALL;
     Completion createErrorCompletion(ExecState *, ErrorType, const char *msg, const Identifier &) KJS_FAST_CALL;
@@ -159,10 +155,6 @@ namespace KJS {
 
     int m_line : 31;
     bool m_mayHaveDeclarations : 1;
-  private:
-    // disallow assignment
-    Node& operator=(const Node&) KJS_FAST_CALL;
-    Node(const Node &other) KJS_FAST_CALL;
   };
     
     class ExpressionNode : public Node {
@@ -186,7 +178,10 @@ namespace KJS {
         
         virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL = 0;
         virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
-    };
+
+        // Used to optimize those nodes that do extra work when returning a result, even if the result has no semantic relevance
+        virtual void optimizeForUnnecessaryResult() { }
+   };
 
   class StatementNode : public Node {
   public:
@@ -239,10 +234,10 @@ namespace KJS {
   
   class ImmediateNumberNode : public NumberNode {
   public:
-      ImmediateNumberNode(JSValue* v, double d) KJS_FAST_CALL : NumberNode(d), m_value(v) { ASSERT(v == JSImmediate::fromDouble(d)); }
+      ImmediateNumberNode(JSValue* v, double d) KJS_FAST_CALL : NumberNode(d), m_value(v) { ASSERT(v == JSImmediate::from(d)); }
       virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
       
-      virtual void setValue(double d) KJS_FAST_CALL { m_double = d; m_value = JSImmediate::fromDouble(d); ASSERT(m_value); }
+      virtual void setValue(double d) KJS_FAST_CALL { m_double = d; m_value = JSImmediate::from(d); ASSERT(m_value); }
   private:
       JSValue* m_value;
   };
@@ -321,16 +316,19 @@ namespace KJS {
     ALWAYS_INLINE JSValue* inlineEvaluate(ExecState*);
   };
 
-  class ElementNode : public ExpressionNode {
+  class ElementNode : public Node {
   public:
     ElementNode(int e, ExpressionNode* n) KJS_FAST_CALL : elision(e), node(n) { }
     ElementNode(ElementNode* l, int e, ExpressionNode* n) KJS_FAST_CALL
       : elision(e), node(n) { l->next = this; }
-    virtual void optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack&) KJS_FAST_CALL;
-    virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+    virtual Precedence precedence() const { ASSERT_NOT_REACHED(); return PrecExpression; }
     virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+    virtual void optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack&) KJS_FAST_CALL;
+
     PassRefPtr<ElementNode> releaseNext() KJS_FAST_CALL { return next.release(); }
-    virtual Precedence precedence() const { ASSERT_NOT_REACHED(); return PrecExpression; }
+
+    JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+
   private:
     friend class ArrayNode;
     ListRefPtr<ElementNode> next;
@@ -355,34 +353,38 @@ namespace KJS {
     bool opt;
   };
 
-  class PropertyNode : public ExpressionNode {
+  class PropertyNode : public Node {
   public:
     enum Type { Constant, Getter, Setter };
     PropertyNode(const Identifier& n, ExpressionNode* a, Type t) KJS_FAST_CALL
       : m_name(n), assign(a), type(t) { }
     virtual void optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack&) KJS_FAST_CALL;
-    virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
     virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
-    friend class PropertyListNode;
     virtual Precedence precedence() const { ASSERT_NOT_REACHED(); return PrecExpression; }
+
+    JSValue* evaluate(ExecState*) KJS_FAST_CALL;
     const Identifier& name() const { return m_name; }
+
   private:
+    friend class PropertyListNode;
     Identifier m_name;
     RefPtr<ExpressionNode> assign;
     Type type;
   };
   
-  class PropertyListNode : public ExpressionNode {
+  class PropertyListNode : public Node {
   public:
     PropertyListNode(PropertyNode* n) KJS_FAST_CALL
       : node(n) { }
     PropertyListNode(PropertyNode* n, PropertyListNode* l) KJS_FAST_CALL
       : node(n) { l->next = this; }
     virtual void optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack&) KJS_FAST_CALL;
-    virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
     virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
-    PassRefPtr<PropertyListNode> releaseNext() KJS_FAST_CALL { return next.release(); }
     virtual Precedence precedence() const { ASSERT_NOT_REACHED(); return PrecExpression; }
+
+    JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+    PassRefPtr<PropertyListNode> releaseNext() KJS_FAST_CALL { return next.release(); }
+
   private:
     friend class ObjectLiteralNode;
     RefPtr<PropertyNode> node;
@@ -439,33 +441,35 @@ namespace KJS {
     Identifier ident;
   };
 
-  class ArgumentListNode : public ExpressionNode {
+  class ArgumentListNode : public Node {
   public:
     ArgumentListNode(ExpressionNode* e) KJS_FAST_CALL : expr(e) { }
     ArgumentListNode(ArgumentListNode* l, ExpressionNode* e) KJS_FAST_CALL 
       : expr(e) { l->next = this; }
     virtual void optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack&) KJS_FAST_CALL;
-    virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
-    void evaluateList(ExecState*, List&) KJS_FAST_CALL;
     virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
-    PassRefPtr<ArgumentListNode> releaseNext() KJS_FAST_CALL { return next.release(); }
     virtual Precedence precedence() const { ASSERT_NOT_REACHED(); return PrecExpression; }
+
+    void evaluateList(ExecState*, List&) KJS_FAST_CALL;
+    PassRefPtr<ArgumentListNode> releaseNext() KJS_FAST_CALL { return next.release(); }
+
   private:
     friend class ArgumentsNode;
     ListRefPtr<ArgumentListNode> next;
     RefPtr<ExpressionNode> expr;
   };
 
-  class ArgumentsNode : public ExpressionNode {
+  class ArgumentsNode : public Node {
   public:
     ArgumentsNode() KJS_FAST_CALL { }
     ArgumentsNode(ArgumentListNode* l) KJS_FAST_CALL
       : listNode(l) { }
     virtual void optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack&) KJS_FAST_CALL;
-    virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
-    void evaluateList(ExecState* exec, List& list) KJS_FAST_CALL { if (listNode) listNode->evaluateList(exec, list); }
     virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
     virtual Precedence precedence() const { ASSERT_NOT_REACHED(); return PrecExpression; }
+
+    void evaluateList(ExecState* exec, List& list) KJS_FAST_CALL { if (listNode) listNode->evaluateList(exec, list); }
+
   private:
     RefPtr<ArgumentListNode> listNode;
   };
@@ -559,7 +563,7 @@ namespace KJS {
     RefPtr<ArgumentsNode> args;
   };
 
-    class PrePostResolveNode : public ExpressionNode {
+  class PrePostResolveNode : public ExpressionNode {
   public:
     PrePostResolveNode(const Identifier& i) KJS_FAST_CALL : m_ident(i) {}
       
@@ -633,7 +637,7 @@ namespace KJS {
     virtual void optimizeForUnnecessaryResult();
   };
 
-    class PostfixBracketNode : public ExpressionNode {
+  class PostfixBracketNode : public ExpressionNode {
   public:
     PostfixBracketNode(ExpressionNode* b, ExpressionNode* s) KJS_FAST_CALL : m_base(b), m_subscript(s) {}
     virtual void optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack&) KJS_FAST_CALL;
index 1ebd3848fad0dba43cec06871682b604009d162a..f96f76de1d23efe154ceb65f3a272810e6683220 100644 (file)
@@ -200,10 +200,46 @@ inline JSValue *jsBoolean(bool b)
 
 ALWAYS_INLINE JSValue* jsNumber(double d)
 {
-    JSValue *v = JSImmediate::fromDouble(d);
+    JSValue* v = JSImmediate::from(d);
     return v ? v : jsNumberCell(d);
 }
 
+ALWAYS_INLINE JSValue* jsNumber(int i)
+{
+    JSValue* v = JSImmediate::from(i);
+    return v ? v : jsNumberCell(i);
+}
+
+ALWAYS_INLINE JSValue* jsNumber(unsigned i)
+{
+    JSValue* v = JSImmediate::from(i);
+    return v ? v : jsNumberCell(i);
+}
+
+ALWAYS_INLINE JSValue* jsNumber(long i)
+{
+    JSValue* v = JSImmediate::from(i);
+    return v ? v : jsNumberCell(i);
+}
+
+ALWAYS_INLINE JSValue* jsNumber(unsigned long i)
+{
+    JSValue* v = JSImmediate::from(i);
+    return v ? v : jsNumberCell(i);
+}
+
+ALWAYS_INLINE JSValue* jsNumber(long long i)
+{
+    JSValue* v = JSImmediate::from(i);
+    return v ? v : jsNumberCell(i);
+}
+
+ALWAYS_INLINE JSValue* jsNumber(unsigned long long i)
+{
+    JSValue* v = JSImmediate::from(i);
+    return v ? v : jsNumberCell(i);
+}
+
 ALWAYS_INLINE JSValue* jsNumberFromAnd(ExecState *exec, JSValue* v1, JSValue* v2)
 {
     if (JSImmediate::areBothImmediateNumbers(v1, v2))