Index: src/parser.cc |
=================================================================== |
--- src/parser.cc (revision 5319) |
+++ src/parser.cc (working copy) |
@@ -32,6 +32,7 @@ |
#include "bootstrapper.h" |
#include "codegen.h" |
#include "compiler.h" |
+#include "func-name-inferrer.h" |
#include "messages.h" |
#include "parser.h" |
#include "platform.h" |
@@ -154,6 +155,7 @@ |
bool is_pre_parsing_; |
ScriptDataImpl* pre_data_; |
bool seen_loop_stmt_; // Used for inner loop detection. |
+ FuncNameInferrer* fni_; |
bool inside_with() const { return with_nesting_level_ > 0; } |
ParserFactory* factory() const { return factory_; } |
@@ -1214,7 +1216,8 @@ |
log_(log), |
is_pre_parsing_(is_pre_parsing == PREPARSE), |
pre_data_(pre_data), |
- seen_loop_stmt_(false) { |
+ seen_loop_stmt_(false), |
+ fni_(NULL) { |
} |
@@ -1243,6 +1246,7 @@ |
HistogramTimerScope timer(&Counters::parse); |
Counters::total_parse_size.Increment(source->length()); |
+ fni_ = new FuncNameInferrer(); |
// Initialize parser state. |
source->TryFlatten(); |
@@ -1303,6 +1307,9 @@ |
HistogramTimerScope timer(&Counters::parse_lazy); |
Counters::total_parse_size.Increment(source->length()); |
+ fni_ = new FuncNameInferrer(); |
+ fni_->PushEnclosingName(name); |
+ |
// Initialize parser state. |
source->TryFlatten(); |
scanner_.Initialize(source, start_position, end_position, JAVASCRIPT); |
@@ -2080,9 +2087,12 @@ |
VariableProxy* last_var = NULL; // the last variable declared |
int nvars = 0; // the number of variables declared |
do { |
+ if (fni_ != NULL) fni_->Enter(); |
+ |
// Parse variable name. |
if (nvars > 0) Consume(Token::COMMA); |
Handle<String> name = ParseIdentifier(CHECK_OK); |
+ if (fni_ != NULL) fni_->PushVariableName(name); |
// Declare variable. |
// Note that we *always* must treat the initial value via a separate init |
@@ -2134,6 +2144,8 @@ |
Expect(Token::ASSIGN, CHECK_OK); |
position = scanner().location().beg_pos; |
value = ParseAssignmentExpression(accept_IN, CHECK_OK); |
+ // Don't infer if it is "a = function(){...}();"-like expression. |
+ if (fni_ != NULL && value->AsCall() == NULL) fni_->Infer(); |
} |
// Make sure that 'const c' actually initializes 'c' to undefined |
@@ -2210,6 +2222,8 @@ |
Assignment* assignment = NEW(Assignment(op, last_var, value, position)); |
if (block) block->AddStatement(NEW(ExpressionStatement(assignment))); |
} |
+ |
+ if (fni_ != NULL) fni_->Leave(); |
} while (peek() == Token::COMMA); |
if (!is_const && nvars == 1) { |
@@ -2822,9 +2836,11 @@ |
// ConditionalExpression |
// LeftHandSideExpression AssignmentOperator AssignmentExpression |
+ if (fni_ != NULL) fni_->Enter(); |
Expression* expression = ParseConditionalExpression(accept_IN, CHECK_OK); |
if (!Token::IsAssignmentOp(peek())) { |
+ if (fni_ != NULL) fni_->Leave(); |
// Parsed conditional expression only (no assignment). |
return expression; |
} |
@@ -2855,6 +2871,19 @@ |
temp_scope_->AddProperty(); |
} |
+ if (fni_ != NULL) { |
+ // Check if the right hand side is a call to avoid inferring a |
+ // name if we're dealing with "a = function(){...}();"-like |
+ // expression. |
+ if ((op == Token::INIT_VAR |
+ || op == Token::INIT_CONST |
+ || op == Token::ASSIGN) |
+ && (right->AsCall() == NULL)) { |
+ fni_->Infer(); |
+ } |
+ fni_->Leave(); |
+ } |
+ |
return NEW(Assignment(op, expression, right, pos)); |
} |
@@ -3125,6 +3154,7 @@ |
int pos = scanner().location().beg_pos; |
Handle<String> name = ParseIdentifierName(CHECK_OK); |
result = factory()->NewProperty(result, NEW(Literal(name)), pos); |
+ if (fni_ != NULL) fni_->PushLiteralName(name); |
break; |
} |
@@ -3211,6 +3241,7 @@ |
int pos = scanner().location().beg_pos; |
Handle<String> name = ParseIdentifierName(CHECK_OK); |
result = factory()->NewProperty(result, NEW(Literal(name)), pos); |
+ if (fni_ != NULL) fni_->PushLiteralName(name); |
break; |
} |
case Token::LPAREN: { |
@@ -3321,6 +3352,7 @@ |
case Token::IDENTIFIER: { |
Handle<String> name = ParseIdentifier(CHECK_OK); |
+ if (fni_ != NULL) fni_->PushVariableName(name); |
if (is_pre_parsing_) { |
result = VariableProxySentinel::identifier_proxy(); |
} else { |
@@ -3343,6 +3375,7 @@ |
factory()->LookupSymbol(scanner_.literal_string(), |
scanner_.literal_length()); |
result = NEW(Literal(symbol)); |
+ if (fni_ != NULL) fni_->PushLiteralName(symbol); |
break; |
} |
@@ -3640,6 +3673,8 @@ |
Expect(Token::LBRACE, CHECK_OK); |
while (peek() != Token::RBRACE) { |
+ if (fni_ != NULL) fni_->Enter(); |
+ |
Literal* key = NULL; |
Token::Value next = peek(); |
switch (next) { |
@@ -3648,6 +3683,8 @@ |
bool is_setter = false; |
Handle<String> id = |
ParseIdentifierOrGetOrSet(&is_getter, &is_setter, CHECK_OK); |
+ if (fni_ != NULL) fni_->PushLiteralName(id); |
+ |
if ((is_getter || is_setter) && peek() != Token::COLON) { |
ObjectLiteral::Property* property = |
ParseObjectLiteralGetSet(is_getter, CHECK_OK); |
@@ -3656,6 +3693,11 @@ |
} |
properties.Add(property); |
if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK); |
+ |
+ if (fni_ != NULL) { |
+ fni_->Infer(); |
+ fni_->Leave(); |
+ } |
continue; // restart the while |
} |
// Failed to parse as get/set property, so it's just a property |
@@ -3668,6 +3710,7 @@ |
Handle<String> string = |
factory()->LookupSymbol(scanner_.literal_string(), |
scanner_.literal_length()); |
+ if (fni_ != NULL) fni_->PushLiteralName(string); |
uint32_t index; |
if (!string.is_null() && string->AsArrayIndex(&index)) { |
key = NewNumberLiteral(index); |
@@ -3711,6 +3754,11 @@ |
// TODO(1240767): Consider allowing trailing comma. |
if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK); |
+ |
+ if (fni_ != NULL) { |
+ fni_->Infer(); |
+ fni_->Leave(); |
+ } |
} |
Expect(Token::RBRACE, CHECK_OK); |
// Computation of literal_index must happen before pre parse bailout. |
@@ -3922,6 +3970,7 @@ |
// when peeling or unrolling such a loop. |
seen_loop_stmt_ = true; |
+ if (fni_ != NULL && !is_named) fni_->AddFunction(function_literal); |
return function_literal; |
} |
} |