Commit 7708d4a2 authored by marja@chromium.org's avatar marja@chromium.org

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
parent 84520308
......@@ -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<Expression*>* 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<String> 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
......
......@@ -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<ParserTraits> {
// 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<ParserTraits> {
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<ParserTraits> {
}
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<ParserTraits> {
// 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<ParserTraits> {
ScriptDataImpl** cached_data_;
CachedDataMode cached_data_mode_;
Mode mode_;
CompilationInfo* info_;
};
......
......@@ -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 ::
......
......@@ -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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment