From 9b94d12fd75c2cd5d5cab612a8cb6e6375e9828a Mon Sep 17 00:00:00 2001 From: "marja@chromium.org" Date: Mon, 17 Mar 2014 13:54:42 +0000 Subject: [PATCH] Move ParseBinaryExpression to ParserBase. R=mstarzinger@chromium.org BUG=v8:3126 LOG=N Review URL: https://codereview.chromium.org/196933005 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@19997 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/parser.cc | 159 ++++++++++++++++++++++--------------------------------- src/parser.h | 10 +++- src/preparser.cc | 23 +------- src/preparser.h | 69 +++++++++++++++++++++++- 4 files changed, 139 insertions(+), 122 deletions(-) diff --git a/src/parser.cc b/src/parser.cc index d61404e..62e9cba 100644 --- a/src/parser.cc +++ b/src/parser.cc @@ -478,6 +478,66 @@ void ParserTraits::CheckStrictModeLValue(Expression* expression, } +bool ParserTraits::ShortcutNumericLiteralBinaryExpression( + Expression** x, Expression* y, Token::Value op, int pos, + AstNodeFactory* factory) { + if ((*x)->AsLiteral() && (*x)->AsLiteral()->value()->IsNumber() && + y->AsLiteral() && y->AsLiteral()->value()->IsNumber()) { + double x_val = (*x)->AsLiteral()->value()->Number(); + double y_val = y->AsLiteral()->value()->Number(); + switch (op) { + case Token::ADD: + *x = factory->NewNumberLiteral(x_val + y_val, pos); + return true; + case Token::SUB: + *x = factory->NewNumberLiteral(x_val - y_val, pos); + return true; + case Token::MUL: + *x = factory->NewNumberLiteral(x_val * y_val, pos); + return true; + case Token::DIV: + *x = factory->NewNumberLiteral(x_val / y_val, pos); + return true; + case Token::BIT_OR: { + int value = DoubleToInt32(x_val) | DoubleToInt32(y_val); + *x = factory->NewNumberLiteral(value, pos); + return true; + } + case Token::BIT_AND: { + int value = DoubleToInt32(x_val) & DoubleToInt32(y_val); + *x = factory->NewNumberLiteral(value, pos); + return true; + } + case Token::BIT_XOR: { + int value = DoubleToInt32(x_val) ^ DoubleToInt32(y_val); + *x = factory->NewNumberLiteral(value, pos); + return true; + } + case Token::SHL: { + int value = DoubleToInt32(x_val) << (DoubleToInt32(y_val) & 0x1f); + *x = factory->NewNumberLiteral(value, pos); + return true; + } + case Token::SHR: { + uint32_t shift = DoubleToInt32(y_val) & 0x1f; + uint32_t value = DoubleToUint32(x_val) >> shift; + *x = factory->NewNumberLiteral(value, pos); + return true; + } + case Token::SAR: { + uint32_t shift = DoubleToInt32(y_val) & 0x1f; + int value = ArithmeticShiftRight(DoubleToInt32(x_val), shift); + *x = factory->NewNumberLiteral(value, pos); + return true; + } + default: + break; + } + } + return false; +} + + void ParserTraits::ReportMessageAt(Scanner::Location source_location, const char* message, Vector args, @@ -633,9 +693,8 @@ FunctionLiteral* ParserTraits::ParseFunctionLiteral( } -Expression* ParserTraits::ParseBinaryExpression(int prec, bool accept_IN, - bool* ok) { - return parser_->ParseBinaryExpression(prec, accept_IN, ok); +Expression* ParserTraits::ParseUnaryExpression(bool* ok) { + return parser_->ParseUnaryExpression(ok); } @@ -2923,100 +2982,6 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) { } -// Precedence >= 4 -Expression* Parser::ParseBinaryExpression(int prec, bool accept_IN, bool* ok) { - ASSERT(prec >= 4); - Expression* x = ParseUnaryExpression(CHECK_OK); - for (int prec1 = Precedence(peek(), accept_IN); prec1 >= prec; prec1--) { - // prec1 >= 4 - while (Precedence(peek(), accept_IN) == prec1) { - Token::Value op = Next(); - int pos = position(); - Expression* y = ParseBinaryExpression(prec1 + 1, accept_IN, CHECK_OK); - - // Compute some expressions involving only number literals. - if (x && x->AsLiteral() && x->AsLiteral()->value()->IsNumber() && - y && y->AsLiteral() && y->AsLiteral()->value()->IsNumber()) { - double x_val = x->AsLiteral()->value()->Number(); - double y_val = y->AsLiteral()->value()->Number(); - - switch (op) { - case Token::ADD: - x = factory()->NewNumberLiteral(x_val + y_val, pos); - continue; - case Token::SUB: - x = factory()->NewNumberLiteral(x_val - y_val, pos); - continue; - case Token::MUL: - x = factory()->NewNumberLiteral(x_val * y_val, pos); - continue; - case Token::DIV: - x = factory()->NewNumberLiteral(x_val / y_val, pos); - continue; - case Token::BIT_OR: { - int value = DoubleToInt32(x_val) | DoubleToInt32(y_val); - x = factory()->NewNumberLiteral(value, pos); - continue; - } - case Token::BIT_AND: { - int value = DoubleToInt32(x_val) & DoubleToInt32(y_val); - x = factory()->NewNumberLiteral(value, pos); - continue; - } - case Token::BIT_XOR: { - int value = DoubleToInt32(x_val) ^ DoubleToInt32(y_val); - x = factory()->NewNumberLiteral(value, pos); - continue; - } - case Token::SHL: { - int value = DoubleToInt32(x_val) << (DoubleToInt32(y_val) & 0x1f); - x = factory()->NewNumberLiteral(value, pos); - continue; - } - case Token::SHR: { - uint32_t shift = DoubleToInt32(y_val) & 0x1f; - uint32_t value = DoubleToUint32(x_val) >> shift; - x = factory()->NewNumberLiteral(value, pos); - continue; - } - case Token::SAR: { - uint32_t shift = DoubleToInt32(y_val) & 0x1f; - int value = ArithmeticShiftRight(DoubleToInt32(x_val), shift); - x = factory()->NewNumberLiteral(value, pos); - continue; - } - default: - break; - } - } - - // For now we distinguish between comparisons and other binary - // operations. (We could combine the two and get rid of this - // code and AST node eventually.) - if (Token::IsCompareOp(op)) { - // We have a comparison. - Token::Value cmp = op; - switch (op) { - case Token::NE: cmp = Token::EQ; break; - case Token::NE_STRICT: cmp = Token::EQ_STRICT; break; - default: break; - } - x = factory()->NewCompareOperation(cmp, x, y, pos); - if (cmp != op) { - // The comparison was negated - add a NOT. - x = factory()->NewUnaryOperation(Token::NOT, x, pos); - } - - } else { - // We have a "normal" binary operation. - x = factory()->NewBinaryOperation(op, x, y, pos); - } - } - } - return x; -} - - Expression* Parser::ParseUnaryExpression(bool* ok) { // UnaryExpression :: // PostfixExpression diff --git a/src/parser.h b/src/parser.h index a80d31c..0c9857a 100644 --- a/src/parser.h +++ b/src/parser.h @@ -498,6 +498,13 @@ class ParserTraits { // in strict mode. void CheckStrictModeLValue(Expression*expression, bool* ok); + // Returns true if we have a binary expression between two numeric + // literals. In that case, *x will be changed to an expression which is the + // computed value. + bool ShortcutNumericLiteralBinaryExpression( + Expression** x, Expression* y, Token::Value op, int pos, + AstNodeFactory* factory); + // Reporting errors. void ReportMessageAt(Scanner::Location source_location, const char* message, @@ -561,7 +568,7 @@ class ParserTraits { int function_token_position, FunctionLiteral::FunctionType type, bool* ok); - Expression* ParseBinaryExpression(int prec, bool accept_IN, bool* ok); + Expression* ParseUnaryExpression(bool* ok); private: Parser* parser_; @@ -704,7 +711,6 @@ class Parser : public ParserBase { // Support for hamony block scoped bindings. Block* ParseScopedBlock(ZoneStringList* labels, bool* ok); - Expression* ParseBinaryExpression(int prec, bool accept_IN, bool* ok); Expression* ParseUnaryExpression(bool* ok); Expression* ParsePostfixExpression(bool* ok); Expression* ParseLeftHandSideExpression(bool* ok); diff --git a/src/preparser.cc b/src/preparser.cc index 704a050..8a621b4 100644 --- a/src/preparser.cc +++ b/src/preparser.cc @@ -146,10 +146,8 @@ PreParserExpression PreParserTraits::ParseFunctionLiteral( } -PreParserExpression PreParserTraits::ParseBinaryExpression(int prec, - bool accept_IN, - bool* ok) { - return pre_parser_->ParseBinaryExpression(prec, accept_IN, ok); +PreParserExpression PreParserTraits::ParseUnaryExpression(bool* ok) { + return pre_parser_->ParseUnaryExpression(ok); } @@ -844,23 +842,6 @@ PreParser::Statement PreParser::ParseDebuggerStatement(bool* ok) { #undef DUMMY -// Precedence >= 4 -PreParser::Expression PreParser::ParseBinaryExpression(int prec, - bool accept_IN, - bool* ok) { - Expression result = ParseUnaryExpression(CHECK_OK); - for (int prec1 = Precedence(peek(), accept_IN); prec1 >= prec; prec1--) { - // prec1 >= 4 - while (Precedence(peek(), accept_IN) == prec1) { - Next(); - ParseBinaryExpression(prec1 + 1, accept_IN, CHECK_OK); - result = Expression::Default(); - } - } - return result; -} - - PreParser::Expression PreParser::ParseUnaryExpression(bool* ok) { // UnaryExpression :: // PostfixExpression diff --git a/src/preparser.h b/src/preparser.h index 5a242eb..562d209 100644 --- a/src/preparser.h +++ b/src/preparser.h @@ -390,6 +390,9 @@ class ParserBase : public Traits { typename Traits::Type::Expression ParseYieldExpression(bool* ok); typename Traits::Type::Expression ParseConditionalExpression(bool accept_IN, bool* ok); + typename Traits::Type::Expression ParseBinaryExpression(int prec, + bool accept_IN, + bool* ok); // Used to detect duplicates in object literals. Each of the values // kGetterProperty, kSetterProperty and kValueProperty represents @@ -663,11 +666,21 @@ class PreParserFactory { int pos) { return PreParserExpression::Default(); } + PreParserExpression NewUnaryOperation(Token::Value op, + PreParserExpression expression, + int pos) { + return PreParserExpression::Default(); + } PreParserExpression NewBinaryOperation(Token::Value op, PreParserExpression left, PreParserExpression right, int pos) { return PreParserExpression::Default(); } + PreParserExpression NewCompareOperation(Token::Value op, + PreParserExpression left, + PreParserExpression right, int pos) { + return PreParserExpression::Default(); + } PreParserExpression NewArrayLiteral(PreParserExpressionList values, int literal_index, int pos) { @@ -818,6 +831,13 @@ class PreParserTraits { // in strict mode. void CheckStrictModeLValue(PreParserExpression expression, bool* ok); + bool ShortcutNumericLiteralBinaryExpression(PreParserExpression* x, + PreParserExpression y, + Token::Value op, + int pos, + PreParserFactory* factory) { + return false; + } // Reporting errors. void ReportMessageAt(Scanner::Location location, @@ -900,7 +920,7 @@ class PreParserTraits { int function_token_position, FunctionLiteral::FunctionType type, bool* ok); - PreParserExpression ParseBinaryExpression(int prec, bool accept_IN, bool* ok); + PreParserExpression ParseUnaryExpression(bool* ok); private: PreParser* pre_parser_; @@ -1066,7 +1086,6 @@ class PreParser : public ParserBase { Statement ParseTryStatement(bool* ok); Statement ParseDebuggerStatement(bool* ok); Expression ParseConditionalExpression(bool accept_IN, bool* ok); - Expression ParseBinaryExpression(int prec, bool accept_IN, bool* ok); Expression ParseUnaryExpression(bool* ok); Expression ParsePostfixExpression(bool* ok); Expression ParseLeftHandSideExpression(bool* ok); @@ -1729,6 +1748,52 @@ ParserBase::ParseConditionalExpression(bool accept_IN, bool* ok) { } +// Precedence >= 4 +template +typename Traits::Type::Expression +ParserBase::ParseBinaryExpression(int prec, bool accept_IN, bool* ok) { + ASSERT(prec >= 4); + typename Traits::Type::Expression x = this->ParseUnaryExpression(CHECK_OK); + for (int prec1 = Precedence(peek(), accept_IN); prec1 >= prec; prec1--) { + // prec1 >= 4 + while (Precedence(peek(), accept_IN) == prec1) { + Token::Value op = Next(); + int pos = position(); + typename Traits::Type::Expression y = + ParseBinaryExpression(prec1 + 1, accept_IN, CHECK_OK); + + if (this->ShortcutNumericLiteralBinaryExpression(&x, y, op, pos, + factory())) { + continue; + } + + // For now we distinguish between comparisons and other binary + // operations. (We could combine the two and get rid of this + // code and AST node eventually.) + if (Token::IsCompareOp(op)) { + // We have a comparison. + Token::Value cmp = op; + switch (op) { + case Token::NE: cmp = Token::EQ; break; + case Token::NE_STRICT: cmp = Token::EQ_STRICT; break; + default: break; + } + x = factory()->NewCompareOperation(cmp, x, y, pos); + if (cmp != op) { + // The comparison was negated - add a NOT. + x = factory()->NewUnaryOperation(Token::NOT, x, pos); + } + + } else { + // We have a "normal" binary operation. + x = factory()->NewBinaryOperation(op, x, y, pos); + } + } + } + return x; +} + + #undef CHECK_OK #undef CHECK_OK_CUSTOM -- 2.7.4