Index: src/preparser.h |
diff --git a/src/preparser.h b/src/preparser.h |
index 7a92347bc86e6b257b3819bb31a8237ce9346abf..7977fe2fd5362df0639cf01f9d9fd8a95064fe19 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<PreParserTraits> { |
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<Traits>::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<Traits>::ParsePostfixExpression(bool* ok) { |
} |
+template <class Traits> |
+typename ParserBase<Traits>::ExpressionT |
+ParserBase<Traits>::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 |