2007-11-10 Eric Seidel <eric@webkit.org>
authoreseidel <eseidel@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 12 Nov 2007 00:34:37 +0000 (00:34 +0000)
committereseidel <eseidel@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 12 Nov 2007 00:34:37 +0000 (00:34 +0000)
        Reviewed by darin.

        Add simple type inferencing to the parser, and create custom
        AddNode and LessNode subclasses based on inferred types.
        http://bugs.webkit.org/show_bug.cgi?id=15884

        SunSpider claims this is at least a 0.5% speedup.

        * JavaScriptCore.exp:
        * kjs/grammar.y:
        * kjs/internal.cpp:
        (KJS::NumberImp::getPrimitiveNumber):
        (KJS::GetterSetterImp::getPrimitiveNumber):
        * kjs/internal.h:
        * kjs/lexer.cpp:
        (KJS::Lexer::lex):
        * kjs/nodes.cpp:
        (KJS::Node::Node):
        (KJS::StringNode::evaluate):
        (KJS::StringNode::evaluateToNumber):
        (KJS::StringNode::evaluateToBoolean):
        (KJS::RegExpNode::evaluate):
        (KJS::UnaryPlusNode::optimizeVariableAccess):
        (KJS::AddNode::evaluate):
        (KJS::AddNode::evaluateToNumber):
        (KJS::AddNumbersNode::inlineEvaluateToNumber):
        (KJS::AddNumbersNode::evaluate):
        (KJS::AddNumbersNode::evaluateToNumber):
        (KJS::AddStringsNode::evaluate):
        (KJS::AddStringLeftNode::evaluate):
        (KJS::AddStringRightNode::evaluate):
        (KJS::lessThan):
        (KJS::lessThanEq):
        (KJS::LessNumbersNode::evaluate):
        (KJS::LessStringsNode::evaluate):
        * kjs/nodes.h:
        (KJS::ExpressionNode::):
        (KJS::RegExpNode::):
        (KJS::RegExpNode::precedence):
        (KJS::TypeOfResolveNode::):
        (KJS::LocalVarTypeOfNode::):
        (KJS::UnaryPlusNode::):
        (KJS::UnaryPlusNode::precedence):
        (KJS::AddNode::):
        (KJS::AddNode::precedence):
        (KJS::AddNumbersNode::):
        (KJS::AddStringLeftNode::):
        (KJS::AddStringRightNode::):
        (KJS::AddStringsNode::):
        (KJS::LessNode::):
        (KJS::LessNode::precedence):
        (KJS::LessNumbersNode::):
        (KJS::LessStringsNode::):
        * kjs/nodes2string.cpp:
        (KJS::StringNode::streamTo):
        * kjs/object.cpp:
        * kjs/object.h:
        * kjs/value.h:
        (KJS::JSValue::getPrimitiveNumber):

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

13 files changed:
JavaScriptCore/ChangeLog
JavaScriptCore/JavaScriptCore.exp
JavaScriptCore/kjs/grammar.y
JavaScriptCore/kjs/internal.cpp
JavaScriptCore/kjs/internal.h
JavaScriptCore/kjs/lexer.cpp
JavaScriptCore/kjs/nodes.cpp
JavaScriptCore/kjs/nodes.h
JavaScriptCore/kjs/nodes2string.cpp
JavaScriptCore/kjs/object.cpp
JavaScriptCore/kjs/object.h
JavaScriptCore/kjs/value.h
WebCore/WebCore.xcodeproj/project.pbxproj

index a6c818b6fb4b19065d9f453e8c0a5a578c5bb243..676f3b07de775add76049db82069d9b8516e3275 100644 (file)
@@ -1,3 +1,65 @@
+2007-11-10  Eric Seidel  <eric@webkit.org>
+
+        Reviewed by darin.
+        
+        Add simple type inferencing to the parser, and create custom
+        AddNode and LessNode subclasses based on inferred types.
+        http://bugs.webkit.org/show_bug.cgi?id=15884
+        
+        SunSpider claims this is at least a 0.5% speedup.
+
+        * JavaScriptCore.exp:
+        * kjs/grammar.y:
+        * kjs/internal.cpp:
+        (KJS::NumberImp::getPrimitiveNumber):
+        (KJS::GetterSetterImp::getPrimitiveNumber):
+        * kjs/internal.h:
+        * kjs/lexer.cpp:
+        (KJS::Lexer::lex):
+        * kjs/nodes.cpp:
+        (KJS::Node::Node):
+        (KJS::StringNode::evaluate):
+        (KJS::StringNode::evaluateToNumber):
+        (KJS::StringNode::evaluateToBoolean):
+        (KJS::RegExpNode::evaluate):
+        (KJS::UnaryPlusNode::optimizeVariableAccess):
+        (KJS::AddNode::evaluate):
+        (KJS::AddNode::evaluateToNumber):
+        (KJS::AddNumbersNode::inlineEvaluateToNumber):
+        (KJS::AddNumbersNode::evaluate):
+        (KJS::AddNumbersNode::evaluateToNumber):
+        (KJS::AddStringsNode::evaluate):
+        (KJS::AddStringLeftNode::evaluate):
+        (KJS::AddStringRightNode::evaluate):
+        (KJS::lessThan):
+        (KJS::lessThanEq):
+        (KJS::LessNumbersNode::evaluate):
+        (KJS::LessStringsNode::evaluate):
+        * kjs/nodes.h:
+        (KJS::ExpressionNode::):
+        (KJS::RegExpNode::):
+        (KJS::RegExpNode::precedence):
+        (KJS::TypeOfResolveNode::):
+        (KJS::LocalVarTypeOfNode::):
+        (KJS::UnaryPlusNode::):
+        (KJS::UnaryPlusNode::precedence):
+        (KJS::AddNode::):
+        (KJS::AddNode::precedence):
+        (KJS::AddNumbersNode::):
+        (KJS::AddStringLeftNode::):
+        (KJS::AddStringRightNode::):
+        (KJS::AddStringsNode::):
+        (KJS::LessNode::):
+        (KJS::LessNode::precedence):
+        (KJS::LessNumbersNode::):
+        (KJS::LessStringsNode::):
+        * kjs/nodes2string.cpp:
+        (KJS::StringNode::streamTo):
+        * kjs/object.cpp:
+        * kjs/object.h:
+        * kjs/value.h:
+        (KJS::JSValue::getPrimitiveNumber):
+
 2007-11-11  Darin Adler  <darin@apple.com>
 
         - try another way of fixing dftables builds -- refactor pcre_internal.h a bit
index 5bd99d0b7585b70e5ce742c7ad617144ffc0b508..d0556f38d5d8a81f3783b7f4dac24880815c4a73 100644 (file)
@@ -269,8 +269,7 @@ __ZNK3KJS8Bindings8Instance10rootObjectEv
 __ZNK3KJS8JSObject11hasPropertyEPNS_9ExecStateERKNS_10IdentifierE
 __ZNK3KJS8JSObject12defaultValueEPNS_9ExecStateENS_6JSTypeE
 __ZNK3KJS8JSObject14implementsCallEv
-__ZNK3KJS8JSObject18getPrimitiveNumberEPNS_9ExecStateERd
-__ZNK3KJS8JSObject18getPrimitiveNumberEPNS_9ExecStateERd
+__ZN3KJS8JSObject18getPrimitiveNumberEPNS_9ExecStateERdRPNS_7JSValueE
 __ZNK3KJS8JSObject19implementsConstructEv
 __ZNK3KJS8JSObject21implementsHasInstanceEv
 __ZNK3KJS8JSObject3getEPNS_9ExecStateERKNS_10IdentifierE
index 0e2f658408a7700cacd30e9f254d8819a8ab638f..1ab252b55dc540e663b3af831347e859a0844a42 100644 (file)
@@ -57,6 +57,8 @@ static bool allowAutomaticSemicolon();
 
 using namespace KJS;
 
+static AddNode* makeAddNode(ExpressionNode*, ExpressionNode*);
+static LessNode* makeLessNode(ExpressionNode*, ExpressionNode*);
 static ExpressionNode* makeAssignNode(ExpressionNode* loc, Operator, ExpressionNode* expr);
 static ExpressionNode* makePrefixNode(ExpressionNode* expr, Operator);
 static ExpressionNode* makePostfixNode(ExpressionNode* expr, Operator);
@@ -84,30 +86,36 @@ static NumberNode* makeNumberNode(double);
 %}
 
 %union {
-  int                 ival;
-  double              dval;
-  UString             *ustr;
-  Identifier          *ident;
-  ExpressionNode      *node;
-  StatementNode       *stat;
-  ParameterList       param;
-  FunctionBodyNode    *body;
-  FuncDeclNode        *func;
-  FuncExprNode        *funcExpr;
-  ProgramNode         *prog;
-  AssignExprNode      *init;
-  SourceElements      *srcs;
-  ArgumentsNode       *args;
-  ArgumentList        alist;
-  VarDeclNode         *decl;
-  VarDeclList         vlist;
-  CaseBlockNode       *cblk;
-  ClauseList          clist;
-  CaseClauseNode      *ccl;
-  ElementList         elm;
-  Operator            op;
-  PropertyList        plist;
-  PropertyNode       *pnode;
+    int                 intValue;
+    double              doubleValue;
+    UString*            string;
+    Identifier*         ident;
+
+    // expression subtrees
+    ExpressionNode*     expressionNode;
+    FuncDeclNode*       funcDeclNode;
+    PropertyNode*       propertyNode;
+    ArgumentsNode*      argumentsNode;
+    VarDeclNode*        varDeclNode;
+    CaseBlockNode*      caseBlockNode;
+    CaseClauseNode*     caseClauseNode;
+    FuncExprNode*       funcExprNode;
+    AssignExprNode*     assignExprNode;
+
+    // statement nodes
+    StatementNode*      statementNode;
+    FunctionBodyNode*   functionBodyNode;
+    ProgramNode*        programNode;
+
+    SourceElements*     sourceElements;
+    PropertyList        propertyList;
+    ArgumentList        argumentList;
+    VarDeclList         varDeclList;
+    ClauseList          clauseList;
+    ElementList         elementList;
+    ParameterList       parameterList;
+
+    Operator            op;
 }
 
 %start Program
@@ -143,66 +151,66 @@ static NumberNode* makeNumberNode(double);
 %token XOREQUAL OREQUAL            /* ^= and |= */
 
 /* terminal types */
-%token <dval> NUMBER
-%token <ustr> STRING
+%token <doubleValue> NUMBER
+%token <string> STRING
 %token <ident> IDENT
 
 /* automatically inserted semicolon */
 %token AUTOPLUSPLUS AUTOMINUSMINUS
 
 /* non-terminal types */
-%type <node>  Literal ArrayLiteral
-
-%type <node>  PrimaryExpr PrimaryExprNoBrace
-%type <node>  MemberExpr MemberExprNoBF /* BF => brace or function */
-%type <node>  NewExpr NewExprNoBF
-%type <node>  CallExpr CallExprNoBF
-%type <node>  LeftHandSideExpr LeftHandSideExprNoBF
-%type <node>  PostfixExpr PostfixExprNoBF
-%type <node>  UnaryExpr UnaryExprNoBF UnaryExprCommon
-%type <node>  MultiplicativeExpr MultiplicativeExprNoBF
-%type <node>  AdditiveExpr AdditiveExprNoBF
-%type <node>  ShiftExpr ShiftExprNoBF
-%type <node>  RelationalExpr RelationalExprNoIn RelationalExprNoBF
-%type <node>  EqualityExpr EqualityExprNoIn EqualityExprNoBF
-%type <node>  BitwiseANDExpr BitwiseANDExprNoIn BitwiseANDExprNoBF
-%type <node>  BitwiseXORExpr BitwiseXORExprNoIn BitwiseXORExprNoBF
-%type <node>  BitwiseORExpr BitwiseORExprNoIn BitwiseORExprNoBF
-%type <node>  LogicalANDExpr LogicalANDExprNoIn LogicalANDExprNoBF
-%type <node>  LogicalORExpr LogicalORExprNoIn LogicalORExprNoBF
-%type <node>  ConditionalExpr ConditionalExprNoIn ConditionalExprNoBF
-%type <node>  AssignmentExpr AssignmentExprNoIn AssignmentExprNoBF
-%type <node>  Expr ExprNoIn ExprNoBF
-
-%type <node>  ExprOpt ExprNoInOpt
-
-%type <stat>  Statement Block
-%type <stat>  VariableStatement ConstStatement EmptyStatement ExprStatement
-%type <stat>  IfStatement IterationStatement ContinueStatement
-%type <stat>  BreakStatement ReturnStatement WithStatement
-%type <stat>  SwitchStatement LabelledStatement
-%type <stat>  ThrowStatement TryStatement
-%type <stat>  DebuggerStatement
-%type <stat>  SourceElement
-
-%type <init>  Initializer InitializerNoIn
-%type <func>  FunctionDeclaration
-%type <funcExpr>  FunctionExpr
-%type <body>  FunctionBody
-%type <srcs>  SourceElements
-%type <param> FormalParameterList
-%type <op>    AssignmentOperator
-%type <args>  Arguments
-%type <alist> ArgumentList
-%type <vlist> VariableDeclarationList VariableDeclarationListNoIn ConstDeclarationList
-%type <decl>  VariableDeclaration VariableDeclarationNoIn ConstDeclaration
-%type <cblk>  CaseBlock
-%type <ccl>   CaseClause DefaultClause
-%type <clist> CaseClauses CaseClausesOpt
-%type <ival>  Elision ElisionOpt
-%type <elm>   ElementList
-%type <pnode> Property
-%type <plist> PropertyList
+%type <expressionNode>  Literal ArrayLiteral
+
+%type <expressionNode>  PrimaryExpr PrimaryExprNoBrace
+%type <expressionNode>  MemberExpr MemberExprNoBF /* BF => brace or function */
+%type <expressionNode>  NewExpr NewExprNoBF
+%type <expressionNode>  CallExpr CallExprNoBF
+%type <expressionNode>  LeftHandSideExpr LeftHandSideExprNoBF
+%type <expressionNode>  PostfixExpr PostfixExprNoBF
+%type <expressionNode>  UnaryExpr UnaryExprNoBF UnaryExprCommon
+%type <expressionNode>  MultiplicativeExpr MultiplicativeExprNoBF
+%type <expressionNode>  AdditiveExpr AdditiveExprNoBF
+%type <expressionNode>  ShiftExpr ShiftExprNoBF
+%type <expressionNode>  RelationalExpr RelationalExprNoIn RelationalExprNoBF
+%type <expressionNode>  EqualityExpr EqualityExprNoIn EqualityExprNoBF
+%type <expressionNode>  BitwiseANDExpr BitwiseANDExprNoIn BitwiseANDExprNoBF
+%type <expressionNode>  BitwiseXORExpr BitwiseXORExprNoIn BitwiseXORExprNoBF
+%type <expressionNode>  BitwiseORExpr BitwiseORExprNoIn BitwiseORExprNoBF
+%type <expressionNode>  LogicalANDExpr LogicalANDExprNoIn LogicalANDExprNoBF
+%type <expressionNode>  LogicalORExpr LogicalORExprNoIn LogicalORExprNoBF
+%type <expressionNode>  ConditionalExpr ConditionalExprNoIn ConditionalExprNoBF
+%type <expressionNode>  AssignmentExpr AssignmentExprNoIn AssignmentExprNoBF
+%type <expressionNode>  Expr ExprNoIn ExprNoBF
+
+%type <expressionNode>  ExprOpt ExprNoInOpt
+
+%type <statementNode>   Statement Block
+%type <statementNode>   VariableStatement ConstStatement EmptyStatement ExprStatement
+%type <statementNode>   IfStatement IterationStatement ContinueStatement
+%type <statementNode>   BreakStatement ReturnStatement WithStatement
+%type <statementNode>   SwitchStatement LabelledStatement
+%type <statementNode>   ThrowStatement TryStatement
+%type <statementNode>   DebuggerStatement
+%type <statementNode>   SourceElement
+
+%type <assignExprNode>  Initializer InitializerNoIn
+%type <funcDeclNode>    FunctionDeclaration
+%type <funcExprNode>    FunctionExpr
+%type <functionBodyNode>  FunctionBody
+%type <sourceElements>  SourceElements
+%type <parameterList>   FormalParameterList
+%type <op>              AssignmentOperator
+%type <argumentsNode>   Arguments
+%type <argumentList>    ArgumentList
+%type <varDeclList>     VariableDeclarationList VariableDeclarationListNoIn ConstDeclarationList
+%type <varDeclNode>     VariableDeclaration VariableDeclarationNoIn ConstDeclaration
+%type <caseBlockNode>   CaseBlock
+%type <caseClauseNode>  CaseClause DefaultClause
+%type <clauseList>      CaseClauses CaseClausesOpt
+%type <intValue>        Elision ElisionOpt
+%type <elementList>     ElementList
+%type <propertyNode>    Property
+%type <propertyList>    PropertyList
 %%
 
 Literal:
@@ -262,7 +270,7 @@ ArrayLiteral:
 ;
 
 ElementList:
-    ElisionOpt AssignmentExpr           { $$.head = new ElementNode($1, $2); 
+    ElisionOpt AssignmentExpr           { $$.head = new ElementNode($1, $2);
                                           $$.tail = $$.head; }
   | ElementList ',' ElisionOpt AssignmentExpr
                                         { $$.head = $1.head;
@@ -394,14 +402,14 @@ MultiplicativeExprNoBF:
 
 AdditiveExpr:
     MultiplicativeExpr
-  | AdditiveExpr '+' MultiplicativeExpr { $$ = new AddNode($1, $3); }
+  | AdditiveExpr '+' MultiplicativeExpr { $$ = makeAddNode($1, $3); }
   | AdditiveExpr '-' MultiplicativeExpr { $$ = new SubNode($1, $3); }
 ;
 
 AdditiveExprNoBF:
     MultiplicativeExprNoBF
   | AdditiveExprNoBF '+' MultiplicativeExpr
-                                        { $$ = new AddNode($1, $3); }
+                                        { $$ = makeAddNode($1, $3); }
   | AdditiveExprNoBF '-' MultiplicativeExpr
                                         { $$ = new SubNode($1, $3); }
 ;
@@ -422,7 +430,7 @@ ShiftExprNoBF:
 
 RelationalExpr:
     ShiftExpr
-  | RelationalExpr '<' ShiftExpr        { $$ = new LessNode($1, $3); }
+  | RelationalExpr '<' ShiftExpr        { $$ = makeLessNode($1, $3); }
   | RelationalExpr '>' ShiftExpr        { $$ = new GreaterNode($1, $3); }
   | RelationalExpr LE ShiftExpr         { $$ = new LessEqNode($1, $3); }
   | RelationalExpr GE ShiftExpr         { $$ = new GreaterEqNode($1, $3); }
@@ -432,7 +440,7 @@ RelationalExpr:
 
 RelationalExprNoIn:
     ShiftExpr
-  | RelationalExprNoIn '<' ShiftExpr    { $$ = new LessNode($1, $3); }
+  | RelationalExprNoIn '<' ShiftExpr    { $$ = makeLessNode($1, $3); }
   | RelationalExprNoIn '>' ShiftExpr    { $$ = new GreaterNode($1, $3); }
   | RelationalExprNoIn LE ShiftExpr     { $$ = new LessEqNode($1, $3); }
   | RelationalExprNoIn GE ShiftExpr     { $$ = new GreaterEqNode($1, $3); }
@@ -442,7 +450,7 @@ RelationalExprNoIn:
 
 RelationalExprNoBF:
     ShiftExprNoBF
-  | RelationalExprNoBF '<' ShiftExpr    { $$ = new LessNode($1, $3); }
+  | RelationalExprNoBF '<' ShiftExpr    { $$ = makeLessNode($1, $3); }
   | RelationalExprNoBF '>' ShiftExpr    { $$ = new GreaterNode($1, $3); }
   | RelationalExprNoBF LE ShiftExpr     { $$ = new LessEqNode($1, $3); }
   | RelationalExprNoBF GE ShiftExpr     { $$ = new GreaterEqNode($1, $3); }
@@ -887,6 +895,39 @@ SourceElement:
  
 %%
 
+static AddNode* makeAddNode(ExpressionNode* left, ExpressionNode* right)
+{
+    JSType t1 = left->expectedReturnType();
+    JSType t2 = right->expectedReturnType();
+
+    if (t1 == NumberType && t2 == NumberType)
+        return new AddNumbersNode(left, right);
+    if (t1 == StringType && t2 == StringType)
+        return new AddStringsNode(left, right);
+    if (t1 == StringType)
+        return new AddStringLeftNode(left, right);
+    if (t2 == StringType)
+        return new AddStringRightNode(left, right);
+    return new AddNode(left, right);
+}
+
+static LessNode* makeLessNode(ExpressionNode* left, ExpressionNode* right)
+{
+    JSType t1 = left->expectedReturnType();
+    JSType t2 = right->expectedReturnType();
+    
+    if (t1 == StringType && t2 == StringType)
+        return new LessStringsNode(left, right);
+
+    // There are certainly more efficient ways to do this type check if necessary
+    if (t1 == NumberType || t1 == BooleanType || t1 == UndefinedType || t1 == NullType ||
+        t2 == NumberType || t2 == BooleanType || t2 == UndefinedType || t2 == NullType)
+        return new LessNumbersNode(left, right);
+
+    // Neither is certain to be a number, nor were both certain to be strings, so we use the default (slow) implementation.
+    return new LessNode(left, right);
+}
+
 static ExpressionNode* makeAssignNode(ExpressionNode* loc, Operator op, ExpressionNode* expr)
 {
     if (!loc->isLocation())
index f6ecc51c829a77a8a9cc34fd3f61c0c52f635138..125244e2e66ed534153b0dd395d57baf332122e7 100644 (file)
@@ -56,8 +56,9 @@ JSValue* StringImp::toPrimitive(ExecState*, JSType) const
   return const_cast<StringImp*>(this);
 }
 
-bool StringImp::getPrimitiveNumber(ExecState*, double& number) const
+bool StringImp::getPrimitiveNumber(ExecState*, double& number, JSValue*& value)
 {
+    value = this;
     number = val.toDouble();
     return false;
 }
@@ -89,9 +90,10 @@ JSValue* NumberImp::toPrimitive(ExecState*, JSType) const
     return const_cast<NumberImp*>(this);
 }
 
-bool NumberImp::getPrimitiveNumber(ExecState*, double& number) const
+bool NumberImp::getPrimitiveNumber(ExecState*, double& number, JSValue*& value)
 {
     number = val;
+    value = this;
     return true;
 }
 
@@ -158,10 +160,11 @@ JSValue* GetterSetterImp::toPrimitive(ExecState*, JSType) const
     return jsNull();
 }
 
-bool GetterSetterImp::getPrimitiveNumber(ExecState*, double& number) const
+bool GetterSetterImp::getPrimitiveNumber(ExecState*, double& number, JSValue*& value)
 {
-    ASSERT(false);
+    ASSERT_NOT_REACHED();
     number = 0;
+    value = 0;
     return true;
 }
 
index 584cefc430863569f6219fa44a791f15d7628e2f..c4e5c77c822b3cb3c977a32768604add6cd29a2e 100644 (file)
@@ -55,7 +55,7 @@ namespace KJS {
     virtual JSType type() const { return StringType; }
 
     virtual JSValue* toPrimitive(ExecState*, JSType preferred = UnspecifiedType) const;
-    virtual bool getPrimitiveNumber(ExecState*, double& number) const;
+    virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue*& value);
     virtual bool toBoolean(ExecState *exec) const;
     virtual double toNumber(ExecState *exec) const;
     virtual JSObject *toObject(ExecState *exec) const;
@@ -73,7 +73,7 @@ namespace KJS {
     virtual JSType type() const { return NumberType; }
 
     virtual JSValue* toPrimitive(ExecState*, JSType preferred = UnspecifiedType) const;
-    virtual bool getPrimitiveNumber(ExecState*, double& number) const;
+    virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue*& value);
     virtual bool toBoolean(ExecState *exec) const;
     virtual double toNumber(ExecState *exec) const;
     virtual UString toString(ExecState *exec) const;
index 6d184d8911c67c92e3e3afed2c9db9d376b3b1d8..09c12607d609df088bcf661b66efc6a56551943f 100644 (file)
@@ -556,11 +556,11 @@ int Lexer::lex()
       restrKeyword = true;
     break;
   case String:
-    kjsyylval.ustr = makeUString(buffer16, pos16);
+    kjsyylval.string = makeUString(buffer16, pos16);
     token = STRING;
     break;
   case Number:
-    kjsyylval.dval = dval;
+    kjsyylval.doubleValue = dval;
     token = NUMBER;
     break;
   case Bad:
index c88f4025d393505d55ecf174a320a3288ad131ce..9e9155b2171bcaec661508e9c6ee240bbf33a877 100644 (file)
@@ -127,6 +127,7 @@ static HashCountedSet<Node*>* nodeExtraRefCounts;
 
 Node::Node()
     : m_mayHaveDeclarations(false)
+    , m_expectedReturnType(ObjectType)
 {
 #ifndef NDEBUG
     ++NodeCounter::count;
@@ -137,6 +138,19 @@ Node::Node()
   newNodes->add(this);
 }
 
+Node::Node(JSType expectedReturn)
+    : m_mayHaveDeclarations(false)
+    , m_expectedReturnType(expectedReturn)
+{
+#ifndef NDEBUG
+    ++NodeCounter::count;
+#endif
+    m_line = Lexer::curr()->lineNo();
+    if (!newNodes)
+        newNodes = new HashSet<Node*>;
+    newNodes->add(this);
+}
+
 Node::~Node()
 {
 #ifndef NDEBUG
@@ -420,31 +434,31 @@ JSValue* ImmediateNumberNode::evaluate(ExecState*)
 
 // ------------------------------ StringNode -----------------------------------
 
-JSValue *StringNode::evaluate(ExecState *)
+JSValue* StringNode::evaluate(ExecState*)
 {
-  return jsOwnedString(value);
+  return jsOwnedString(m_value);
 }
 
 double StringNode::evaluateToNumber(ExecState*)
 {
-    return value.toDouble();
+    return m_value.toDouble();
 }
 
 bool StringNode::evaluateToBoolean(ExecState*)
 {
-    return !value.isEmpty();
+    return !m_value.isEmpty();
 }
     
 // ------------------------------ RegExpNode -----------------------------------
 
-JSValue *RegExpNode::evaluate(ExecState *exec)
+JSValue* RegExpNode::evaluate(ExecState* exec)
 {
   List list;
-  list.append(jsOwnedString(pattern));
-  list.append(jsOwnedString(flags));
+  list.append(jsOwnedString(m_pattern));
+  list.append(jsOwnedString(m_flags));
 
-  JSObject *reg = exec->lexicalInterpreter()->builtinRegExp();
-  return reg->construct(exec,list);
+  JSObjectreg = exec->lexicalInterpreter()->builtinRegExp();
+  return reg->construct(exec, list);
 }
 
 // ------------------------------ ThisNode -------------------------------------
@@ -1632,13 +1646,13 @@ JSValue* PrefixErrorNode::evaluate(ExecState* exec)
 
 void UnaryPlusNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
 {
-    nodeStack.append(expr.get());
+    nodeStack.append(m_expr.get());
 }
 
 // ECMA 11.4.6
-JSValue *UnaryPlusNode::evaluate(ExecState *exec)
+JSValue* UnaryPlusNode::evaluate(ExecState* exec)
 {
-  JSValue *v = expr->evaluate(exec);
+  JSValue *v = m_expr->evaluate(exec);
   KJS_CHECKEXCEPTIONVALUE
 
   return v->toJSNumber(exec);
@@ -1710,10 +1724,7 @@ double MultNode::inlineEvaluateToNumber(ExecState* exec)
 {
     double n1 = term1->evaluateToNumber(exec);
     KJS_CHECKEXCEPTIONNUMBER
-    
     double n2 = term2->evaluateToNumber(exec);
-    KJS_CHECKEXCEPTIONNUMBER
-    
     return n1 * n2;
 }
 
@@ -1738,10 +1749,7 @@ double DivNode::inlineEvaluateToNumber(ExecState* exec)
 {
     double n1 = term1->evaluateToNumber(exec);
     KJS_CHECKEXCEPTIONNUMBER
-    
     double n2 = term2->evaluateToNumber(exec);
-    KJS_CHECKEXCEPTIONNUMBER
-    
     return n1 / n2;
 }
 
@@ -1766,10 +1774,7 @@ double ModNode::inlineEvaluateToNumber(ExecState* exec)
 {
     double n1 = term1->evaluateToNumber(exec);
     KJS_CHECKEXCEPTIONNUMBER
-    
     double n2 = term2->evaluateToNumber(exec);
-    KJS_CHECKEXCEPTIONNUMBER
-    
     return fmod(n1, n2);
 }
 
@@ -1887,12 +1892,12 @@ void AddNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeS
 }
 
 // ECMA 11.6.1
-JSValue *AddNode::evaluate(ExecState *exec)
+JSValue* AddNode::evaluate(ExecState* exec)
 {
-  JSValue *v1 = term1->evaluate(exec);
+  JSValuev1 = term1->evaluate(exec);
   KJS_CHECKEXCEPTIONVALUE
 
-  JSValue *v2 = term2->evaluate(exec);
+  JSValuev2 = term2->evaluate(exec);
   KJS_CHECKEXCEPTIONVALUE
 
   return add(exec, v1, v2);
@@ -1900,15 +1905,68 @@ JSValue *AddNode::evaluate(ExecState *exec)
 
 double AddNode::evaluateToNumber(ExecState* exec)
 {
-    JSValue *v1 = term1->evaluate(exec);
+    JSValuev1 = term1->evaluate(exec);
     KJS_CHECKEXCEPTIONNUMBER
     
-    JSValue *v2 = term2->evaluate(exec);
+    JSValuev2 = term2->evaluate(exec);
     KJS_CHECKEXCEPTIONNUMBER
     
     return addToNumber(exec, v1, v2);
 }
 
+double AddNumbersNode::inlineEvaluateToNumber(ExecState* exec)
+{
+    double n1 = term1->evaluateToNumber(exec);
+    KJS_CHECKEXCEPTIONNUMBER
+    double n2 = term2->evaluateToNumber(exec);
+    return n1 + n2;
+}
+
+JSValue* AddNumbersNode::evaluate(ExecState* exec)
+{
+    return jsNumber(inlineEvaluateToNumber(exec));
+}
+
+double AddNumbersNode::evaluateToNumber(ExecState* exec)
+{
+    return inlineEvaluateToNumber(exec);
+}
+
+JSValue* AddStringsNode::evaluate(ExecState* exec)
+{
+    JSValue* v1 = term1->evaluate(exec);
+    KJS_CHECKEXCEPTIONVALUE
+    
+    JSValue* v2 = term2->evaluate(exec);
+    KJS_CHECKEXCEPTIONVALUE
+    
+    return jsString(static_cast<StringImp*>(v1)->value() + static_cast<StringImp*>(v2)->value());
+}
+
+JSValue* AddStringLeftNode::evaluate(ExecState* exec)
+{
+    JSValue* v1 = term1->evaluate(exec);
+    KJS_CHECKEXCEPTIONVALUE
+    
+    JSValue* v2 = term2->evaluate(exec);
+    KJS_CHECKEXCEPTIONVALUE
+    
+    JSValue* p2 = v2->toPrimitive(exec, UnspecifiedType);
+    return jsString(static_cast<StringImp*>(v1)->value() + p2->toString(exec));
+}
+
+JSValue* AddStringRightNode::evaluate(ExecState* exec)
+{
+    JSValue* v1 = term1->evaluate(exec);
+    KJS_CHECKEXCEPTIONVALUE
+    
+    JSValue* v2 = term2->evaluate(exec);
+    KJS_CHECKEXCEPTIONVALUE
+    
+    JSValue* p1 = v1->toPrimitive(exec, UnspecifiedType);
+    return jsString(p1->toString(exec) + static_cast<StringImp*>(v2)->value());
+}
+
 void SubNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
 {
     nodeStack.append(term1.get());
@@ -1920,10 +1978,7 @@ double SubNode::inlineEvaluateToNumber(ExecState* exec)
 {
     double n1 = term1->evaluateToNumber(exec);
     KJS_CHECKEXCEPTIONNUMBER
-    
     double n2 = term2->evaluateToNumber(exec);
-    KJS_CHECKEXCEPTIONNUMBER
-    
     return n1 - n2;
 }
 
@@ -2002,26 +2057,30 @@ static inline bool lessThan(ExecState *exec, JSValue* v1, JSValue* v2)
 {
     double n1;
     double n2;
-    bool wasNotString1 = v1->getPrimitiveNumber(exec, n1);
-    bool wasNotString2 = v2->getPrimitiveNumber(exec, n2);
+    JSValue* p1;
+    JSValue* p2;
+    bool wasNotString1 = v1->getPrimitiveNumber(exec, n1, p1);
+    bool wasNotString2 = v2->getPrimitiveNumber(exec, n2, p2);
     
     if (wasNotString1 | wasNotString2)
         return n1 < n2;
 
-    return v1->toString(exec) < v2->toString(exec);
+    return static_cast<const StringImp*>(p1)->value() < static_cast<const StringImp*>(p2)->value();
 }
 
 static inline bool lessThanEq(ExecState *exec, JSValue* v1, JSValue* v2) 
 {
     double n1;
     double n2;
-    bool wasNotString1 = v1->getPrimitiveNumber(exec, n1);
-    bool wasNotString2 = v2->getPrimitiveNumber(exec, n2);
+    JSValue* p1;
+    JSValue* p2;
+    bool wasNotString1 = v1->getPrimitiveNumber(exec, n1, p1);
+    bool wasNotString2 = v2->getPrimitiveNumber(exec, n2, p2);
     
     if (wasNotString1 | wasNotString2)
         return n1 <= n2;
 
-    return !(v2->toString(exec) < v1->toString(exec));
+    return !(static_cast<const StringImp*>(p2)->value() < static_cast<const StringImp*>(p1)->value());
 }
 
 void LessNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
@@ -2049,6 +2108,22 @@ bool LessNode::evaluateToBoolean(ExecState* exec)
     return lessThan(exec, v1, v2);
 }
 
+JSValue* LessNumbersNode::evaluate(ExecState* exec)
+{
+    double n1 = expr1->evaluateToNumber(exec);
+    KJS_CHECKEXCEPTIONVALUE
+    double n2 = expr2->evaluateToNumber(exec);
+    return jsBoolean(n1 < n2);
+}
+
+JSValue* LessStringsNode::evaluate(ExecState* exec)
+{
+    JSValue* v1 = expr1->evaluate(exec);
+    KJS_CHECKEXCEPTIONVALUE
+    JSValue* v2 = expr2->evaluate(exec);
+    return jsBoolean(static_cast<StringImp*>(v1)->value() < static_cast<StringImp*>(v2)->value());
+}
+
 void GreaterNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
 {
     nodeStack.append(expr2.get());
index bded3908ed08a15efeca8956ca5f08fd4d96e547..b65ea772d7c4e607dcfddb7a785f87c057bb5c94 100644 (file)
@@ -135,6 +135,7 @@ namespace KJS {
     virtual void optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack&) KJS_FAST_CALL { }
 
   protected:
+    Node(JSType) KJS_FAST_CALL; // used by ExpressionNode
     Completion createErrorCompletion(ExecState *, ErrorType, const char *msg) KJS_FAST_CALL;
     Completion createErrorCompletion(ExecState *, ErrorType, const char *msg, const Identifier &) KJS_FAST_CALL;
 
@@ -153,19 +154,20 @@ namespace KJS {
 
     Completion rethrowException(ExecState*) KJS_FAST_CALL;
 
-    int m_line : 31;
+    int m_line : 28;
     bool m_mayHaveDeclarations : 1;
+    unsigned m_expectedReturnType : 3; // JSType
   };
     
     class ExpressionNode : public Node {
     public:
-        ExpressionNode() KJS_FAST_CALL { }
+        ExpressionNode() KJS_FAST_CALL : Node() {}
+        ExpressionNode(JSType expectedReturn) KJS_FAST_CALL
+            : Node(expectedReturn) {}
         
         // Special constructor for cases where we overwrite an object in place.
         ExpressionNode(PlacementNewAdoptType) KJS_FAST_CALL
-            : Node(PlacementNewAdopt)
-        {
-        }
+            : Node(PlacementNewAdopt) {}
         
         virtual bool isNumber() const KJS_FAST_CALL { return false; }
         virtual bool isLocation() const KJS_FAST_CALL { return false; }
@@ -173,6 +175,8 @@ namespace KJS {
         virtual bool isBracketAccessorNode() const KJS_FAST_CALL { return false; }
         virtual bool isDotAccessorNode() const KJS_FAST_CALL { return false; }
         
+        JSType expectedReturnType() const KJS_FAST_CALL { return static_cast<JSType>(m_expectedReturnType); }
+        
         virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL = 0;
         virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
         virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
@@ -199,7 +203,7 @@ namespace KJS {
 
   class NullNode : public ExpressionNode {
   public:
-    NullNode() KJS_FAST_CALL }
+    NullNode() KJS_FAST_CALL : ExpressionNode(NullType) {}
     virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
     virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
     virtual Precedence precedence() const { return PrecPrimary; }
@@ -207,7 +211,7 @@ namespace KJS {
 
   class FalseNode : public ExpressionNode {
   public:
-    FalseNode() KJS_FAST_CALL }
+    FalseNode() KJS_FAST_CALL : ExpressionNode(BooleanType) {}
     virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
     virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL { return false; }
     virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
@@ -216,7 +220,7 @@ namespace KJS {
 
   class TrueNode : public ExpressionNode {
   public:
-    TrueNode() KJS_FAST_CALL }
+    TrueNode() KJS_FAST_CALL : ExpressionNode(BooleanType) {}
     virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
     virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL { return true; }
     virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
@@ -225,7 +229,7 @@ namespace KJS {
 
   class NumberNode : public ExpressionNode {
   public:
-    NumberNode(double v) KJS_FAST_CALL : m_double(v) {}
+    NumberNode(double v) KJS_FAST_CALL : ExpressionNode(NumberType), m_double(v) {}
     virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
     virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
     virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
@@ -247,12 +251,12 @@ namespace KJS {
       
       virtual void setValue(double d) KJS_FAST_CALL { m_double = d; m_value = JSImmediate::from(d); ASSERT(m_value); }
   private:
-      JSValue* m_value;
+      JSValue* m_value; // This is never a JSCell, only JSImmediate, thus no ProtectedPtr
   };
 
   class StringNode : public ExpressionNode {
   public:
-    StringNode(const UString *v) KJS_FAST_CALL { value = *v; }
+    StringNode(const UString* v) KJS_FAST_CALL : ExpressionNode(StringType), m_value(*v) {}
     virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
     virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
     virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
@@ -260,18 +264,19 @@ namespace KJS {
     virtual Precedence precedence() const { return PrecPrimary; }
 
   private:
-    UString value;
+    UString m_value;
   };
 
   class RegExpNode : public ExpressionNode {
   public:
-    RegExpNode(const UString &p, const UString &f) KJS_FAST_CALL 
-      : pattern(p), flags(f) { }
+    RegExpNode(const UString& pattern, const UString& flags) KJS_FAST_CALL 
+      : m_pattern(pattern), m_flags(flags) { }
     virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
     virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
     virtual Precedence precedence() const { return PrecPrimary; }
   private:
-    UString pattern, flags;
+    UString m_pattern;
+    UString m_flags;
   };
 
   class ThisNode : public ExpressionNode {
@@ -577,7 +582,7 @@ namespace KJS {
 
   class PrePostResolveNode : public ExpressionNode {
   public:
-    PrePostResolveNode(const Identifier& i) KJS_FAST_CALL : m_ident(i) {}
+    PrePostResolveNode(const Identifier& i) KJS_FAST_CALL : ExpressionNode(NumberType), m_ident(i) {}
       
     PrePostResolveNode(PlacementNewAdoptType) KJS_FAST_CALL 
         : ExpressionNode(PlacementNewAdopt)
@@ -792,14 +797,13 @@ namespace KJS {
   class TypeOfResolveNode : public ExpressionNode {
   public:
     TypeOfResolveNode(const Identifier &s) KJS_FAST_CALL 
-        : m_ident(s) 
-    { 
-    }
+        : ExpressionNode(StringType), m_ident(s) {}
     
     TypeOfResolveNode(PlacementNewAdoptType) KJS_FAST_CALL 
         : ExpressionNode(PlacementNewAdopt)
         , m_ident(PlacementNewAdopt) 
     {
+        m_expectedReturnType = StringType;
     }
 
     virtual void optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack&) KJS_FAST_CALL;
@@ -819,7 +823,8 @@ namespace KJS {
   public:
     LocalVarTypeOfNode(size_t i) KJS_FAST_CALL 
         : TypeOfResolveNode(PlacementNewAdopt)
-    { 
+    {
+        m_expectedReturnType = StringType;
         ASSERT(i != missingSymbolMarker());
         m_index = i;
     }
@@ -829,7 +834,7 @@ namespace KJS {
 
   class TypeOfValueNode : public ExpressionNode {
   public:
-    TypeOfValueNode(ExpressionNode* e) KJS_FAST_CALL : m_expr(e) {}
+    TypeOfValueNode(ExpressionNode* e) KJS_FAST_CALL : ExpressionNode(StringType), m_expr(e) {}
     virtual void optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack&) KJS_FAST_CALL;
     virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
     virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
@@ -970,18 +975,18 @@ namespace KJS {
 
   class UnaryPlusNode : public ExpressionNode {
   public:
-    UnaryPlusNode(ExpressionNode* e) KJS_FAST_CALL : expr(e) {}
+    UnaryPlusNode(ExpressionNode* e) KJS_FAST_CALL : ExpressionNode(NumberType), m_expr(e) {}
     virtual void optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack&) KJS_FAST_CALL;
     virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
     virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
     virtual Precedence precedence() const { return PrecUnary; }
   private:
-    RefPtr<ExpressionNode> expr;
+    RefPtr<ExpressionNode> m_expr;
   };
 
   class NegateNode : public ExpressionNode {
   public:
-    NegateNode(ExpressionNode* e) KJS_FAST_CALL : expr(e) {}
+    NegateNode(ExpressionNode* e) KJS_FAST_CALL : ExpressionNode(NumberType), expr(e) {}
     virtual void optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack&) KJS_FAST_CALL;
     virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
     virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
@@ -993,7 +998,7 @@ namespace KJS {
 
   class BitwiseNotNode : public ExpressionNode {
   public:
-    BitwiseNotNode(ExpressionNode* e) KJS_FAST_CALL : expr(e) {}
+    BitwiseNotNode(ExpressionNode* e) KJS_FAST_CALL : ExpressionNode(NumberType), expr(e) {}
     virtual void optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack&) KJS_FAST_CALL;
     virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
     virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
@@ -1004,7 +1009,7 @@ namespace KJS {
 
   class LogicalNotNode : public ExpressionNode {
   public:
-    LogicalNotNode(ExpressionNode* e) KJS_FAST_CALL : expr(e) {}
+    LogicalNotNode(ExpressionNode* e) KJS_FAST_CALL : ExpressionNode(BooleanType), expr(e) {}
     virtual void optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack&) KJS_FAST_CALL;
     virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
     virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
@@ -1016,7 +1021,7 @@ namespace KJS {
   
   class MultNode : public ExpressionNode {
   public:
-      MultNode(ExpressionNode*  t1, ExpressionNode*  t2) KJS_FAST_CALL : term1(t1), term2(t2) {}
+      MultNode(ExpressionNode* t1, ExpressionNode* t2) KJS_FAST_CALL : ExpressionNode(NumberType), term1(t1), term2(t2) {}
       virtual void optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack&) KJS_FAST_CALL;
       virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
       virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
@@ -1030,7 +1035,7 @@ namespace KJS {
   
   class DivNode : public ExpressionNode {
   public:
-      DivNode(ExpressionNode*  t1, ExpressionNode*  t2) KJS_FAST_CALL : term1(t1), term2(t2) {}
+      DivNode(ExpressionNode* t1, ExpressionNode* t2) KJS_FAST_CALL : ExpressionNode(NumberType), term1(t1), term2(t2) {}
       virtual void optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack&) KJS_FAST_CALL;
       virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
       virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
@@ -1044,7 +1049,7 @@ namespace KJS {
   
   class ModNode : public ExpressionNode {
   public:
-      ModNode(ExpressionNode*  t1, ExpressionNode*  t2) KJS_FAST_CALL : term1(t1), term2(t2) {}
+      ModNode(ExpressionNode* t1, ExpressionNode* t2) KJS_FAST_CALL : ExpressionNode(NumberType), term1(t1), term2(t2) {}
       virtual void optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack&) KJS_FAST_CALL;
       virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
       virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
@@ -1058,20 +1063,48 @@ namespace KJS {
 
   class AddNode : public ExpressionNode {
   public:
-    AddNode(ExpressionNode*  t1, ExpressionNode*  t2) KJS_FAST_CALL : term1(t1), term2(t2) {}
+    AddNode(ExpressionNode* t1, ExpressionNode* t2) KJS_FAST_CALL : term1(t1), term2(t2) {}
     virtual void optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack&) KJS_FAST_CALL;
     virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
     virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
     virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
     virtual Precedence precedence() const { return PrecAdditive; }
-  private:
+  protected:
+    AddNode(ExpressionNode* t1, ExpressionNode* t2, JSType expectedReturn) KJS_FAST_CALL : ExpressionNode(expectedReturn), term1(t1), term2(t2) {}
     RefPtr<ExpressionNode> term1;
     RefPtr<ExpressionNode> term2;
   };
-  
+
+    class AddNumbersNode : public AddNode {
+    public:
+        AddNumbersNode(ExpressionNode* t1, ExpressionNode* t2) KJS_FAST_CALL : AddNode(t1, t2, NumberType) {}
+        virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+        virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
+    private:
+        ALWAYS_INLINE double inlineEvaluateToNumber(ExecState*) KJS_FAST_CALL;
+    };
+
+    class AddStringLeftNode : public AddNode {
+    public:
+        AddStringLeftNode(ExpressionNode* t1, ExpressionNode* t2) KJS_FAST_CALL : AddNode(t1, t2, StringType) {}
+        virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+    };
+
+    class AddStringRightNode : public AddNode {
+    public:
+        AddStringRightNode(ExpressionNode* t1, ExpressionNode* t2) KJS_FAST_CALL : AddNode(t1, t2, StringType) {}
+        virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+    };
+
+    class AddStringsNode : public AddNode {
+    public:
+        AddStringsNode(ExpressionNode* t1, ExpressionNode* t2) KJS_FAST_CALL : AddNode(t1, t2, StringType) {}
+        virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+    };
+
   class SubNode : public ExpressionNode {
   public:
-      SubNode(ExpressionNode*  t1, ExpressionNode*  t2) KJS_FAST_CALL : term1(t1), term2(t2) {}
+      SubNode(ExpressionNode* t1, ExpressionNode* t2) KJS_FAST_CALL : ExpressionNode(NumberType), term1(t1), term2(t2) {}
       virtual void optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack&) KJS_FAST_CALL;
       virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
       virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
@@ -1085,8 +1118,8 @@ namespace KJS {
 
   class LeftShiftNode : public ExpressionNode {
   public:
-    LeftShiftNode(ExpressionNode*  t1, ExpressionNode*  t2) KJS_FAST_CALL
-      : term1(t1), term2(t2) {}
+    LeftShiftNode(ExpressionNode* t1, ExpressionNode* t2) KJS_FAST_CALL
+      : ExpressionNode(NumberType), term1(t1), term2(t2) {}
     virtual void optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack&) KJS_FAST_CALL;
     virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
     virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
@@ -1098,8 +1131,8 @@ namespace KJS {
 
   class RightShiftNode : public ExpressionNode {
   public:
-    RightShiftNode(ExpressionNode*  t1, ExpressionNode*  t2) KJS_FAST_CALL
-      : term1(t1), term2(t2) {}
+    RightShiftNode(ExpressionNode* t1, ExpressionNode* t2) KJS_FAST_CALL
+      : ExpressionNode(NumberType), term1(t1), term2(t2) {}
     virtual void optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack&) KJS_FAST_CALL;
     virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
     virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
@@ -1111,8 +1144,8 @@ namespace KJS {
 
   class UnsignedRightShiftNode : public ExpressionNode {
   public:
-    UnsignedRightShiftNode(ExpressionNode*  t1, ExpressionNode*  t2) KJS_FAST_CALL
-      : term1(t1), term2(t2) {}
+    UnsignedRightShiftNode(ExpressionNode* t1, ExpressionNode* t2) KJS_FAST_CALL
+      : ExpressionNode(NumberType), term1(t1), term2(t2) {}
     virtual void optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack&) KJS_FAST_CALL;
     virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
     virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
@@ -1124,18 +1157,32 @@ namespace KJS {
 
   class LessNode : public ExpressionNode {
   public:
-    LessNode(ExpressionNode* e1, ExpressionNode* e2) KJS_FAST_CALL :
-      expr1(e1), expr2(e2) {}
+    LessNode(ExpressionNode* e1, ExpressionNode* e2) KJS_FAST_CALL
+      : ExpressionNode(BooleanType), expr1(e1), expr2(e2) {}
     virtual void optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack&) KJS_FAST_CALL;
     virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
     virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
     virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
     virtual Precedence precedence() const { return PrecRelational; }
-  private:
+  protected:
     RefPtr<ExpressionNode> expr1;
     RefPtr<ExpressionNode> expr2;
   };
 
+    class LessNumbersNode : public LessNode {
+    public:
+        LessNumbersNode(ExpressionNode* e1, ExpressionNode* e2) KJS_FAST_CALL
+        : LessNode(e1, e2) {}
+        virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+    };
+
+    class LessStringsNode : public LessNode {
+    public:
+        LessStringsNode(ExpressionNode* e1, ExpressionNode* e2) KJS_FAST_CALL
+        : LessNode(e1, e2) {}
+        virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+    };
+
   class GreaterNode : public ExpressionNode {
   public:
     GreaterNode(ExpressionNode* e1, ExpressionNode* e2) KJS_FAST_CALL :
@@ -1180,8 +1227,8 @@ namespace KJS {
 
     class InstanceOfNode : public ExpressionNode {
   public:
-    InstanceOfNode(ExpressionNode* e1, ExpressionNode* e2) KJS_FAST_CALL :
-      expr1(e1), expr2(e2) {}
+    InstanceOfNode(ExpressionNode* e1, ExpressionNode* e2) KJS_FAST_CALL
+        : ExpressionNode(BooleanType), expr1(e1), expr2(e2) {}
     virtual void optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack&) KJS_FAST_CALL;
     virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
     virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
@@ -1209,7 +1256,7 @@ namespace KJS {
     class EqualNode : public ExpressionNode {
   public:
     EqualNode(ExpressionNode* e1, ExpressionNode* e2) KJS_FAST_CALL
-      : expr1(e1), expr2(e2) {}
+        : ExpressionNode(BooleanType), expr1(e1), expr2(e2) {}
     virtual void optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack&) KJS_FAST_CALL;
     virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
     virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
@@ -1223,7 +1270,7 @@ namespace KJS {
     class NotEqualNode : public ExpressionNode {
   public:
     NotEqualNode(ExpressionNode* e1, ExpressionNode* e2) KJS_FAST_CALL
-      : expr1(e1), expr2(e2) {}
+        : ExpressionNode(BooleanType), expr1(e1), expr2(e2) {}
     virtual void optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack&) KJS_FAST_CALL;
     virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
     virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
@@ -1237,7 +1284,7 @@ namespace KJS {
     class StrictEqualNode : public ExpressionNode {
   public:
     StrictEqualNode(ExpressionNode* e1, ExpressionNode* e2) KJS_FAST_CALL
-      : expr1(e1), expr2(e2) {}
+        : ExpressionNode(BooleanType), expr1(e1), expr2(e2) {}
     virtual void optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack&) KJS_FAST_CALL;
     virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
     virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
@@ -1251,7 +1298,7 @@ namespace KJS {
     class NotStrictEqualNode : public ExpressionNode {
   public:
     NotStrictEqualNode(ExpressionNode* e1, ExpressionNode* e2) KJS_FAST_CALL
-      : expr1(e1), expr2(e2) {}
+        : ExpressionNode(BooleanType), expr1(e1), expr2(e2) {}
     virtual void optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack&) KJS_FAST_CALL;
     virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
     virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
@@ -1264,8 +1311,8 @@ namespace KJS {
 
     class BitAndNode : public ExpressionNode {
   public:
-    BitAndNode(ExpressionNode* e1, ExpressionNode* e2) KJS_FAST_CALL :
-      expr1(e1), expr2(e2) {}
+    BitAndNode(ExpressionNode* e1, ExpressionNode* e2) KJS_FAST_CALL
+        : ExpressionNode(NumberType), expr1(e1), expr2(e2) {}
     virtual void optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack&) KJS_FAST_CALL;
     virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
     virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
@@ -1277,8 +1324,8 @@ namespace KJS {
 
     class BitOrNode : public ExpressionNode {
   public:
-    BitOrNode(ExpressionNode* e1, ExpressionNode* e2) KJS_FAST_CALL :
-      expr1(e1), expr2(e2) {}
+    BitOrNode(ExpressionNode* e1, ExpressionNode* e2) KJS_FAST_CALL
+        : ExpressionNode(NumberType), expr1(e1), expr2(e2) {}
     virtual void optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack&) KJS_FAST_CALL;
     virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
     virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
@@ -1290,8 +1337,8 @@ namespace KJS {
 
     class BitXOrNode : public ExpressionNode {
   public:
-    BitXOrNode(ExpressionNode* e1, ExpressionNode* e2) KJS_FAST_CALL :
-      expr1(e1), expr2(e2) {}
+    BitXOrNode(ExpressionNode* e1, ExpressionNode* e2) KJS_FAST_CALL
+        : ExpressionNode(NumberType), expr1(e1), expr2(e2) {}
     virtual void optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack&) KJS_FAST_CALL;
     virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
     virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
@@ -1306,8 +1353,8 @@ namespace KJS {
    */
     class LogicalAndNode : public ExpressionNode {
   public:
-    LogicalAndNode(ExpressionNode* e1, ExpressionNode* e2) KJS_FAST_CALL :
-      expr1(e1), expr2(e2) {}
+    LogicalAndNode(ExpressionNode* e1, ExpressionNode* e2) KJS_FAST_CALL
+        : ExpressionNode(BooleanType), expr1(e1), expr2(e2) {}
     virtual void optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack&) KJS_FAST_CALL;
     virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
     virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
@@ -1320,8 +1367,8 @@ namespace KJS {
   
     class LogicalOrNode : public ExpressionNode {
   public:
-    LogicalOrNode(ExpressionNode* e1, ExpressionNode* e2) KJS_FAST_CALL :
-      expr1(e1), expr2(e2) {}
+    LogicalOrNode(ExpressionNode* e1, ExpressionNode* e2) KJS_FAST_CALL
+        : ExpressionNode(BooleanType), expr1(e1), expr2(e2) {}
     virtual void optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack&) KJS_FAST_CALL;
     virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
     virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
index 1e6f99833d4278993d32059af4451627e27637a0..dc7966bde40e85df803a1b45e6d60d7393626b84 100644 (file)
@@ -285,12 +285,12 @@ void NumberNode::streamTo(SourceStream& s) const
 
 void StringNode::streamTo(SourceStream& s) const
 {
-    s << '"' << escapeStringForPrettyPrinting(value) << '"';
+    s << '"' << escapeStringForPrettyPrinting(m_value) << '"';
 }
 
 void RegExpNode::streamTo(SourceStream& s) const
 { 
-    s << '/' <<  pattern << '/' << flags; 
+    s << '/' <<  m_pattern << '/' << m_flags; 
 }
 
 void ThisNode::streamTo(SourceStream& s) const
@@ -524,7 +524,7 @@ void PrefixErrorNode::streamTo(SourceStream& s) const
 
 void UnaryPlusNode::streamTo(SourceStream& s) const
 {
-    s << "+ " << PrecUnary << expr;
+    s << "+ " << PrecUnary << m_expr;
 }
 
 void NegateNode::streamTo(SourceStream& s) const
index 7f981d4010196d06f12e356687135eada2233e54..13d5e6553658d11a668695b6c63e0604f0191d64 100644 (file)
@@ -354,9 +354,9 @@ static ALWAYS_INLINE JSValue *tryGetAndCallProperty(ExecState *exec, const JSObj
   return NULL;
 }
 
-bool JSObject::getPrimitiveNumber(ExecState* exec, double& number) const
+bool JSObject::getPrimitiveNumber(ExecState* exec, double& number, JSValue*& result)
 {
-    JSValue* result = defaultValue(exec, NumberType);
+    result = defaultValue(exec, NumberType);
     number = result->toNumber(exec);
     return !result->isString();
 }
index 05da150f90c773b86aff82bd05df75b38b3ed67c..1f45f5eb0a21357391f495c02c29638abb18fae5 100644 (file)
@@ -78,7 +78,7 @@ namespace KJS {
     GetterSetterImp() : getter(0), setter(0) { }
       
     virtual JSValue* toPrimitive(ExecState*, JSType preferred = UnspecifiedType) const;
-    virtual bool getPrimitiveNumber(ExecState*, double& number) const;
+    virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue*& value);
     virtual bool toBoolean(ExecState *exec) const;
     virtual double toNumber(ExecState *exec) const;
     virtual UString toString(ExecState *exec) const;
@@ -412,7 +412,7 @@ namespace KJS {
     virtual void getPropertyNames(ExecState*, PropertyNameArray&);
 
     virtual JSValue* toPrimitive(ExecState*, JSType preferredType = UnspecifiedType) const;
-    virtual bool getPrimitiveNumber(ExecState*, double& number) const;
+    virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue*& value);
     virtual bool toBoolean(ExecState *exec) const;
     virtual double toNumber(ExecState *exec) const;
     virtual UString toString(ExecState *exec) const;
index 7d64f3625154526fb65c82abfdf2cf260863483e..c4c3aae6a9f420c4daccea0fc921f4d81ba9c731 100644 (file)
@@ -81,7 +81,7 @@ public:
 
     // Basic conversions.
     JSValue* toPrimitive(ExecState* exec, JSType preferredType = UnspecifiedType) const;
-    bool getPrimitiveNumber(ExecState* exec, double& number) const;
+    bool getPrimitiveNumber(ExecState* exec, double& number, JSValue*& value);
 
     bool toBoolean(ExecState *exec) const;
     double toNumber(ExecState *exec) const;
@@ -149,7 +149,7 @@ public:
 
     // Basic conversions.
     virtual JSValue *toPrimitive(ExecState *exec, JSType preferredType = UnspecifiedType) const = 0;
-    virtual bool getPrimitiveNumber(ExecState* exec, double& number) const = 0;
+    virtual bool getPrimitiveNumber(ExecState* exec, double& number, JSValue*& value) = 0;
     virtual bool toBoolean(ExecState *exec) const = 0;
     virtual double toNumber(ExecState *exec) const = 0;
     virtual UString toString(ExecState *exec) const = 0;
@@ -420,13 +420,14 @@ inline JSValue* JSValue::toPrimitive(ExecState* exec, JSType preferredType) cons
     return JSImmediate::isImmediate(this) ? const_cast<JSValue*>(this) : asCell()->toPrimitive(exec, preferredType);
 }
 
-inline bool JSValue::getPrimitiveNumber(ExecState* exec, double& number) const
+inline bool JSValue::getPrimitiveNumber(ExecState* exec, double& number, JSValue*& value)
 {
     if (JSImmediate::isImmediate(this)) {
         number = JSImmediate::toDouble(this);
+        value = this;
         return true;
     }
-    return asCell()->getPrimitiveNumber(exec, number);
+    return asCell()->getPrimitiveNumber(exec, number, value);
 }
 
 inline bool JSValue::toBoolean(ExecState *exec) const
index ffdf93cbf4a80164ff2a8eff22e62d1a189c9ac8..5a0edeb34d69bf238492b4d679b83f4665ea0115 100644 (file)
                0867D690FE84028FC02AAC07 /* Project object */ = {
                        isa = PBXProject;
                        buildConfigurationList = 149C284308902B11008A9EFC /* Build configuration list for PBXProject "WebCore" */;
+                       compatibilityVersion = "Xcode 2.4";
                        hasScannedForEncodings = 1;
                        knownRegions = (
                                English,