Commit dc7c497d authored by eseidel's avatar eseidel

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):


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@27695 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 54fb9abf
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
......
......@@ -269,8 +269,7 @@ __ZNK3KJS8Bindings8Instance10rootObjectEv
__ZNK3KJS8JSObject11hasPropertyEPNS_9ExecStateERKNS_10IdentifierE
__ZNK3KJS8JSObject12defaultValueEPNS_9ExecStateENS_6JSTypeE
__ZNK3KJS8JSObject14implementsCallEv
__ZNK3KJS8JSObject18getPrimitiveNumberEPNS_9ExecStateERd
__ZNK3KJS8JSObject18getPrimitiveNumberEPNS_9ExecStateERd
__ZN3KJS8JSObject18getPrimitiveNumberEPNS_9ExecStateERdRPNS_7JSValueE
__ZNK3KJS8JSObject19implementsConstructEv
__ZNK3KJS8JSObject21implementsHasInstanceEv
__ZNK3KJS8JSObject3getEPNS_9ExecStateERKNS_10IdentifierE
......
......@@ -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())
......
......@@ -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;
}
......
......@@ -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;
......
......@@ -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:
......
......@@ -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);
JSObject* reg = 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);
JSValue* v1 = term1->evaluate(exec);
KJS_CHECKEXCEPTIONVALUE
JSValue *v2 = term2->evaluate(exec);
JSValue* v2 = 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);
JSValue* v1 = term1->evaluate(exec);
KJS_CHECKEXCEPTIONNUMBER
JSValue *v2 = term2->evaluate(exec);
JSValue* v2 = 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 |