From 7708d4a22d3dade046bc6724cfe9bbc24e355215 Mon Sep 17 00:00:00 2001 From: "marja@chromium.org" Date: Fri, 21 Mar 2014 09:51:33 +0000 Subject: [PATCH] Move ParseLeftHandSideExpression to ParserBase. Includes cleanups: - Reorganized functions in PreParserFactory to be in the logical order. - De-hackified things PreParser doesn't need to track, such as IsCall & IsCallNew. R=mstarzinger@chromium.org BUG= Review URL: https://codereview.chromium.org/206433003 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@20150 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/parser.cc | 87 ++++---------------------- src/parser.h | 37 +++-------- src/preparser.cc | 49 +-------------- src/preparser.h | 186 +++++++++++++++++++++++++++++++++++++++++++------------ 4 files changed, 167 insertions(+), 192 deletions(-) diff --git a/src/parser.cc b/src/parser.cc index 49fd7ba..c0d3360 100644 --- a/src/parser.cc +++ b/src/parser.cc @@ -449,6 +449,16 @@ void ParserTraits::CheckAssigningFunctionLiteralToProperty(Expression* left, } +void ParserTraits::CheckPossibleEvalCall(Expression* expression, + Scope* scope) { + VariableProxy* callee = expression->AsVariableProxy(); + if (callee != NULL && + callee->IsVariable(parser_->isolate()->factory()->eval_string())) { + scope->DeclarationScope()->RecordEvalCall(); + } +} + + Expression* ParserTraits::MarkExpressionAsLValue(Expression* expression) { VariableProxy* proxy = expression != NULL ? expression->AsVariableProxy() @@ -740,8 +750,8 @@ FunctionLiteral* ParserTraits::ParseFunctionLiteral( } -Expression* ParserTraits::ParseLeftHandSideExpression(bool* ok) { - return parser_->ParseLeftHandSideExpression(ok); +Expression* ParserTraits::ParseMemberWithNewPrefixesExpression(bool* ok) { + return parser_->ParseMemberWithNewPrefixesExpression(ok); } @@ -3043,79 +3053,6 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) { } -Expression* Parser::ParseLeftHandSideExpression(bool* ok) { - // LeftHandSideExpression :: - // (NewExpression | MemberExpression) ... - - Expression* result = ParseMemberWithNewPrefixesExpression(CHECK_OK); - - while (true) { - switch (peek()) { - case Token::LBRACK: { - Consume(Token::LBRACK); - int pos = position(); - Expression* index = ParseExpression(true, CHECK_OK); - result = factory()->NewProperty(result, index, pos); - Expect(Token::RBRACK, CHECK_OK); - break; - } - - case Token::LPAREN: { - int pos; - if (scanner()->current_token() == Token::IDENTIFIER) { - // For call of an identifier we want to report position of - // the identifier as position of the call in the stack trace. - pos = position(); - } else { - // For other kinds of calls we record position of the parenthesis as - // position of the call. Note that this is extremely important for - // expressions of the form function(){...}() for which call position - // should not point to the closing brace otherwise it will intersect - // with positions recorded for function literal and confuse debugger. - pos = peek_position(); - // Also the trailing parenthesis are a hint that the function will - // be called immediately. If we happen to have parsed a preceding - // function literal eagerly, we can also compile it eagerly. - if (result->IsFunctionLiteral() && mode() == PARSE_EAGERLY) { - result->AsFunctionLiteral()->set_parenthesized(); - } - } - ZoneList* args = ParseArguments(CHECK_OK); - - // Keep track of eval() calls since they disable all local variable - // optimizations. - // The calls that need special treatment are the - // direct eval calls. These calls are all of the form eval(...), with - // no explicit receiver. - // These calls are marked as potentially direct eval calls. Whether - // they are actually direct calls to eval is determined at run time. - VariableProxy* callee = result->AsVariableProxy(); - if (callee != NULL && - callee->IsVariable(isolate()->factory()->eval_string())) { - scope_->DeclarationScope()->RecordEvalCall(); - } - result = factory()->NewCall(result, args, pos); - if (fni_ != NULL) fni_->RemoveLastFunction(); - break; - } - - case Token::PERIOD: { - Consume(Token::PERIOD); - int pos = position(); - Handle name = ParseIdentifierName(CHECK_OK); - result = factory()->NewProperty( - result, factory()->NewLiteral(name, pos), pos); - if (fni_ != NULL) fni_->PushLiteralName(name); - break; - } - - default: - return result; - } - } -} - - Expression* Parser::ParseMemberWithNewPrefixesExpression(bool* ok) { // NewExpression :: // ('new')+ MemberExpression diff --git a/src/parser.h b/src/parser.h index 333aaf5..4febdc8 100644 --- a/src/parser.h +++ b/src/parser.h @@ -490,6 +490,11 @@ class ParserTraits { static void CheckAssigningFunctionLiteralToProperty(Expression* left, Expression* right); + // Keep track of eval() calls since they disable all local variable + // optimizations. This checks if expression is an eval call, and if yes, + // forwards the information to scope. + void CheckPossibleEvalCall(Expression* expression, Scope* scope); + // Determine if the expression is a variable proxy and mark it as being used // in an assignment or with a increment/decrement operator. This is currently // used on for the statically checking assignments to harmony const bindings. @@ -497,7 +502,7 @@ class ParserTraits { // Checks LHS expression for assignment and prefix/postfix increment/decrement // in strict mode. - void CheckStrictModeLValue(Expression*expression, bool* ok); + 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 @@ -584,7 +589,7 @@ class ParserTraits { int function_token_position, FunctionLiteral::FunctionType type, bool* ok); - Expression* ParseLeftHandSideExpression(bool* ok); + Expression* ParseMemberWithNewPrefixesExpression(bool* ok); private: Parser* parser_; @@ -622,11 +627,6 @@ class Parser : public ParserBase { // https://codereview.chromium.org/7003030/ ). static const int kMaxNumFunctionLocals = 4194303; // 2^22-1 - enum Mode { - PARSE_LAZILY, - PARSE_EAGERLY - }; - enum VariableDeclarationContext { kModuleElement, kBlockElement, @@ -640,22 +640,6 @@ class Parser : public ParserBase { kHasNoInitializers }; - class ParsingModeScope BASE_EMBEDDED { - public: - ParsingModeScope(Parser* parser, Mode mode) - : parser_(parser), - old_mode_(parser->mode()) { - parser_->mode_ = mode; - } - ~ParsingModeScope() { - parser_->mode_ = old_mode_; - } - - private: - Parser* parser_; - Mode old_mode_; - }; - // Returns NULL if parsing failed. FunctionLiteral* ParseProgram(); @@ -685,7 +669,6 @@ class Parser : public ParserBase { } bool inside_with() const { return scope_->inside_with(); } - Mode mode() const { return mode_; } ScriptDataImpl** cached_data() const { return cached_data_; } CachedDataMode cached_data_mode() const { return cached_data_mode_; } Scope* DeclarationScope(VariableMode mode) { @@ -742,14 +725,10 @@ class Parser : public ParserBase { // Support for hamony block scoped bindings. Block* ParseScopedBlock(ZoneStringList* labels, bool* ok); - Expression* ParseUnaryExpression(bool* ok); - Expression* ParseLeftHandSideExpression(bool* ok); Expression* ParseMemberWithNewPrefixesExpression(bool* ok); Expression* ParseMemberExpression(bool* ok); Expression* ParseMemberExpressionContinuation(Expression* expression, bool* ok); - Expression* ParseObjectLiteral(bool* ok); - // Initialize the components of a for-in / for-of statement. void InitializeForEachStatement(ForEachStatement* stmt, Expression* each, @@ -835,8 +814,6 @@ class Parser : public ParserBase { ScriptDataImpl** cached_data_; CachedDataMode cached_data_mode_; - Mode mode_; - CompilationInfo* info_; }; diff --git a/src/preparser.cc b/src/preparser.cc index 9480af6..9473701 100644 --- a/src/preparser.cc +++ b/src/preparser.cc @@ -146,8 +146,9 @@ PreParserExpression PreParserTraits::ParseFunctionLiteral( } -PreParserExpression PreParserTraits::ParseLeftHandSideExpression(bool* ok) { - return pre_parser_->ParseLeftHandSideExpression(ok); +PreParserExpression PreParserTraits::ParseMemberWithNewPrefixesExpression( + bool* ok) { + return pre_parser_->ParseMemberWithNewPrefixesExpression(ok); } @@ -842,50 +843,6 @@ PreParser::Statement PreParser::ParseDebuggerStatement(bool* ok) { #undef DUMMY -PreParser::Expression PreParser::ParseLeftHandSideExpression(bool* ok) { - // LeftHandSideExpression :: - // (NewExpression | MemberExpression) ... - - Expression result = ParseMemberWithNewPrefixesExpression(CHECK_OK); - - while (true) { - switch (peek()) { - case Token::LBRACK: { - Consume(Token::LBRACK); - ParseExpression(true, CHECK_OK); - Expect(Token::RBRACK, CHECK_OK); - if (result.IsThis()) { - result = Expression::ThisProperty(); - } else { - result = Expression::Property(); - } - break; - } - - case Token::LPAREN: { - ParseArguments(CHECK_OK); - result = Expression::Default(); - break; - } - - case Token::PERIOD: { - Consume(Token::PERIOD); - ParseIdentifierName(CHECK_OK); - if (result.IsThis()) { - result = Expression::ThisProperty(); - } else { - result = Expression::Property(); - } - break; - } - - default: - return result; - } - } -} - - PreParser::Expression PreParser::ParseMemberWithNewPrefixesExpression( bool* ok) { // NewExpression :: diff --git a/src/preparser.h b/src/preparser.h index 7a92347..7977fe2 100644 --- a/src/preparser.h +++ b/src/preparser.h @@ -97,6 +97,7 @@ class ParserBase : public Traits { extension_(extension), fni_(NULL), log_(log), + mode_(PARSE_EAGERLY), // Lazy mode must be set explicitly. scanner_(scanner), stack_limit_(stack_limit), stack_overflow_(false), @@ -138,6 +139,11 @@ class ParserBase : public Traits { kDontAllowEvalOrArguments }; + enum Mode { + PARSE_LAZILY, + PARSE_EAGERLY + }; + // --------------------------------------------------------------------------- // FunctionState and BlockState together implement the parser's scope stack. // The parser's current scope is in scope_. BlockState and FunctionState @@ -229,11 +235,28 @@ class ParserBase : public Traits { friend class ParserTraits; }; + class ParsingModeScope BASE_EMBEDDED { + public: + ParsingModeScope(ParserBase* parser, Mode mode) + : parser_(parser), + old_mode_(parser->mode()) { + parser_->mode_ = mode; + } + ~ParsingModeScope() { + parser_->mode_ = old_mode_; + } + + private: + ParserBase* parser_; + Mode old_mode_; + }; + Scanner* scanner() const { return scanner_; } int position() { return scanner_->location().beg_pos; } int peek_position() { return scanner_->peek_location().beg_pos; } bool stack_overflow() const { return stack_overflow_; } void set_stack_overflow() { stack_overflow_ = true; } + Mode mode() const { return mode_; } typename Traits::Type::Zone* zone() const { return zone_; } INLINE(Token::Value peek()) { @@ -396,6 +419,7 @@ class ParserBase : public Traits { ExpressionT ParseBinaryExpression(int prec, bool accept_IN, bool* ok); ExpressionT ParseUnaryExpression(bool* ok); ExpressionT ParsePostfixExpression(bool* ok); + ExpressionT ParseLeftHandSideExpression(bool* ok); // Used to detect duplicates in object literals. Each of the values // kGetterProperty, kSetterProperty and kValueProperty represents @@ -462,6 +486,7 @@ class ParserBase : public Traits { v8::Extension* extension_; FuncNameInferrer* fni_; ParserRecorder* log_; + Mode mode_; private: Scanner* scanner_; @@ -585,17 +610,20 @@ class PreParserExpression { return IsIdentifier() || IsProperty(); } + // At the moment PreParser doesn't track these expression types. + bool IsFunctionLiteral() const { return false; } + bool IsCall() const { return false; } + bool IsCallNew() const { return false; } + + PreParserExpression AsFunctionLiteral() { return *this; } + // Dummy implementation for making expression->somefunc() work in both Parser // and PreParser. PreParserExpression* operator->() { return this; } - // These are only used when doing function name inferring, and PreParser - // doesn't do function name inferring. - void* AsCall() const { return NULL; } - void* AsCallNew() const { return NULL; } - // More dummy implementations of things PreParser doesn't need to track: void set_index(int index) {} // For YieldExpressions + void set_parenthesized() {} private: // Least significant 2 bits are used as flags. Bits 0 and 1 represent @@ -673,26 +701,18 @@ class PreParserScope { class PreParserFactory { public: explicit PreParserFactory(void* extra_param) {} - - PreParserExpression NewRegExpLiteral(PreParserIdentifier js_pattern, - PreParserIdentifier js_flags, - int literal_index, - int pos) { - return PreParserExpression::Default(); - } - PreParserExpression NewUnaryOperation(Token::Value op, - PreParserExpression expression, - int pos) { + PreParserExpression NewLiteral(PreParserIdentifier identifier, + int pos) { return PreParserExpression::Default(); } - PreParserExpression NewBinaryOperation(Token::Value op, - PreParserExpression left, - PreParserExpression right, int pos) { + PreParserExpression NewNumberLiteral(double number, + int pos) { return PreParserExpression::Default(); } - PreParserExpression NewCompareOperation(Token::Value op, - PreParserExpression left, - PreParserExpression right, int pos) { + PreParserExpression NewRegExpLiteral(PreParserIdentifier js_pattern, + PreParserIdentifier js_flags, + int literal_index, + int pos) { return PreParserExpression::Default(); } PreParserExpression NewArrayLiteral(PreParserExpressionList values, @@ -700,18 +720,15 @@ class PreParserFactory { int pos) { return PreParserExpression::Default(); } - PreParserExpression NewObjectLiteralProperty(bool is_getter, PreParserExpression value, int pos) { return PreParserExpression::Default(); } - PreParserExpression NewObjectLiteralProperty(PreParserExpression key, PreParserExpression value) { return PreParserExpression::Default(); } - PreParserExpression NewObjectLiteral(PreParserExpressionList properties, int literal_index, int boilerplate_properties, @@ -719,48 +736,61 @@ class PreParserFactory { int pos) { return PreParserExpression::Default(); } - - PreParserExpression NewLiteral(PreParserIdentifier identifier, - int pos) { + PreParserExpression NewVariableProxy(void* generator_variable) { return PreParserExpression::Default(); } - - PreParserExpression NewNumberLiteral(double number, - int pos) { + PreParserExpression NewProperty(PreParserExpression obj, + PreParserExpression key, + int pos) { + if (obj.IsThis()) { + return PreParserExpression::ThisProperty(); + } + return PreParserExpression::Property(); + } + 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 NewAssignment(Token::Value op, PreParserExpression left, PreParserExpression right, int pos) { return PreParserExpression::Default(); } - - PreParserExpression NewVariableProxy(void* generator_variable) { - return PreParserExpression::Default(); - } - PreParserExpression NewYield(PreParserExpression generator_object, PreParserExpression expression, Yield::Kind yield_kind, int pos) { return PreParserExpression::Default(); } - PreParserExpression NewConditional(PreParserExpression condition, PreParserExpression then_expression, PreParserExpression else_expression, int pos) { return PreParserExpression::Default(); } - PreParserExpression NewCountOperation(Token::Value op, bool is_prefix, PreParserExpression expression, int pos) { return PreParserExpression::Default(); } + PreParserExpression NewCall(PreParserExpression expression, + PreParserExpressionList arguments, + int pos) { + return PreParserExpression::Default(); + } }; @@ -839,6 +869,10 @@ class PreParserTraits { static void CheckAssigningFunctionLiteralToProperty( PreParserExpression left, PreParserExpression right) {} + // PreParser doesn't need to keep track of eval calls. + static void CheckPossibleEvalCall(PreParserExpression expression, + PreParserScope* scope) {} + static PreParserExpression MarkExpressionAsLValue( PreParserExpression expression) { // TODO(marja): To be able to produce the same errors, the preparser needs @@ -945,7 +979,7 @@ class PreParserTraits { int function_token_position, FunctionLiteral::FunctionType type, bool* ok); - PreParserExpression ParseLeftHandSideExpression(bool* ok); + PreParserExpression ParseMemberWithNewPrefixesExpression(bool* ok); private: PreParser* pre_parser_; @@ -1109,7 +1143,6 @@ class PreParser : public ParserBase { Statement ParseTryStatement(bool* ok); Statement ParseDebuggerStatement(bool* ok); Expression ParseConditionalExpression(bool accept_IN, bool* ok); - Expression ParseLeftHandSideExpression(bool* ok); Expression ParseMemberExpression(bool* ok); Expression ParseMemberExpressionContinuation(PreParserExpression expression, bool* ok); @@ -1698,7 +1731,7 @@ ParserBase::ParseAssignmentExpression(bool accept_IN, bool* ok) { if ((op == Token::INIT_VAR || op == Token::INIT_CONST_LEGACY || op == Token::ASSIGN) - && (right->AsCall() == NULL && right->AsCallNew() == NULL)) { + && (!right->IsCall() && !right->IsCallNew())) { fni_->Infer(); } else { fni_->RemoveLastFunction(); @@ -1890,6 +1923,77 @@ ParserBase::ParsePostfixExpression(bool* ok) { } +template +typename ParserBase::ExpressionT +ParserBase::ParseLeftHandSideExpression(bool* ok) { + // LeftHandSideExpression :: + // (NewExpression | MemberExpression) ... + + ExpressionT result = this->ParseMemberWithNewPrefixesExpression(CHECK_OK); + + while (true) { + switch (peek()) { + case Token::LBRACK: { + Consume(Token::LBRACK); + int pos = position(); + ExpressionT index = ParseExpression(true, CHECK_OK); + result = factory()->NewProperty(result, index, pos); + Expect(Token::RBRACK, CHECK_OK); + break; + } + + case Token::LPAREN: { + int pos; + if (scanner()->current_token() == Token::IDENTIFIER) { + // For call of an identifier we want to report position of + // the identifier as position of the call in the stack trace. + pos = position(); + } else { + // For other kinds of calls we record position of the parenthesis as + // position of the call. Note that this is extremely important for + // expressions of the form function(){...}() for which call position + // should not point to the closing brace otherwise it will intersect + // with positions recorded for function literal and confuse debugger. + pos = peek_position(); + // Also the trailing parenthesis are a hint that the function will + // be called immediately. If we happen to have parsed a preceding + // function literal eagerly, we can also compile it eagerly. + if (result->IsFunctionLiteral() && mode() == PARSE_EAGERLY) { + result->AsFunctionLiteral()->set_parenthesized(); + } + } + typename Traits::Type::ExpressionList args = ParseArguments(CHECK_OK); + + // Keep track of eval() calls since they disable all local variable + // optimizations. + // The calls that need special treatment are the + // direct eval calls. These calls are all of the form eval(...), with + // no explicit receiver. + // These calls are marked as potentially direct eval calls. Whether + // they are actually direct calls to eval is determined at run time. + this->CheckPossibleEvalCall(result, scope_); + result = factory()->NewCall(result, args, pos); + if (fni_ != NULL) fni_->RemoveLastFunction(); + break; + } + + case Token::PERIOD: { + Consume(Token::PERIOD); + int pos = position(); + IdentifierT name = ParseIdentifierName(CHECK_OK); + result = factory()->NewProperty( + result, factory()->NewLiteral(name, pos), pos); + if (fni_ != NULL) this->PushLiteralName(fni_, name); + break; + } + + default: + return result; + } + } +} + + #undef CHECK_OK #undef CHECK_OK_CUSTOM -- 2.7.4