Move the function name inferrer code from the AstOptimizer to
the parser in preparation for not using the optimizer when using the full codegen. Code covered by existing tests. Review URL: http://codereview.chromium.org/3141034 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@5321 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
d0bdc7956e
commit
528eb97b3a
@ -44,6 +44,20 @@ void FuncNameInferrer::PushEnclosingName(Handle<String> name) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FuncNameInferrer::PushLiteralName(Handle<String> name) {
|
||||||
|
if (IsOpen() && !Heap::prototype_symbol()->Equals(*name)) {
|
||||||
|
names_stack_.Add(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FuncNameInferrer::PushVariableName(Handle<String> name) {
|
||||||
|
if (IsOpen() && !Heap::result_symbol()->Equals(*name)) {
|
||||||
|
names_stack_.Add(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Handle<String> FuncNameInferrer::MakeNameFromStack() {
|
Handle<String> FuncNameInferrer::MakeNameFromStack() {
|
||||||
if (names_stack_.is_empty()) {
|
if (names_stack_.is_empty()) {
|
||||||
return Factory::empty_string();
|
return Factory::empty_string();
|
||||||
|
@ -36,11 +36,12 @@ namespace internal {
|
|||||||
// Inference is performed in cases when an anonymous function is assigned
|
// Inference is performed in cases when an anonymous function is assigned
|
||||||
// to a variable or a property (see test-func-name-inference.cc for examples.)
|
// to a variable or a property (see test-func-name-inference.cc for examples.)
|
||||||
//
|
//
|
||||||
// The basic idea is that during AST traversal LHSs of expressions are
|
// The basic idea is that during parsing of LHSs of certain expressions
|
||||||
// always visited before RHSs. Thus, during visiting the LHS, a name can be
|
// (assignments, declarations, object literals) we collect name strings,
|
||||||
// collected, and during visiting the RHS, a function literal can be collected.
|
// and during parsing of the RHS, a function literal can be collected. After
|
||||||
// Inference is performed while leaving the assignment node.
|
// parsing the RHS we can infer a name for function literals that do not have
|
||||||
class FuncNameInferrer BASE_EMBEDDED {
|
// a name.
|
||||||
|
class FuncNameInferrer : public ZoneObject {
|
||||||
public:
|
public:
|
||||||
FuncNameInferrer()
|
FuncNameInferrer()
|
||||||
: entries_stack_(10),
|
: entries_stack_(10),
|
||||||
@ -61,11 +62,9 @@ class FuncNameInferrer BASE_EMBEDDED {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Pushes an encountered name onto names stack when in collection state.
|
// Pushes an encountered name onto names stack when in collection state.
|
||||||
void PushName(Handle<String> name) {
|
void PushLiteralName(Handle<String> name);
|
||||||
if (IsOpen()) {
|
|
||||||
names_stack_.Add(name);
|
void PushVariableName(Handle<String> name);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Adds a function to infer name for.
|
// Adds a function to infer name for.
|
||||||
void AddFunction(FunctionLiteral* func_to_infer) {
|
void AddFunction(FunctionLiteral* func_to_infer) {
|
||||||
@ -75,11 +74,16 @@ class FuncNameInferrer BASE_EMBEDDED {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Infers a function name and leaves names collection state.
|
// Infers a function name and leaves names collection state.
|
||||||
void InferAndLeave() {
|
void Infer() {
|
||||||
ASSERT(IsOpen());
|
ASSERT(IsOpen());
|
||||||
if (!funcs_to_infer_.is_empty()) {
|
if (!funcs_to_infer_.is_empty()) {
|
||||||
InferFunctionsNames();
|
InferFunctionsNames();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Infers a function name and leaves names collection state.
|
||||||
|
void Leave() {
|
||||||
|
ASSERT(IsOpen());
|
||||||
names_stack_.Rewind(entries_stack_.RemoveLast());
|
names_stack_.Rewind(entries_stack_.RemoveLast());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,34 +106,6 @@ class FuncNameInferrer BASE_EMBEDDED {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// A wrapper class that automatically calls InferAndLeave when
|
|
||||||
// leaving scope.
|
|
||||||
class ScopedFuncNameInferrer BASE_EMBEDDED {
|
|
||||||
public:
|
|
||||||
explicit ScopedFuncNameInferrer(FuncNameInferrer* inferrer)
|
|
||||||
: inferrer_(inferrer),
|
|
||||||
is_entered_(false) {}
|
|
||||||
|
|
||||||
~ScopedFuncNameInferrer() {
|
|
||||||
if (is_entered_) {
|
|
||||||
inferrer_->InferAndLeave();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Triggers the wrapped inferrer into name collection state.
|
|
||||||
void Enter() {
|
|
||||||
inferrer_->Enter();
|
|
||||||
is_entered_ = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
FuncNameInferrer* inferrer_;
|
|
||||||
bool is_entered_;
|
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(ScopedFuncNameInferrer);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
} } // namespace v8::internal
|
} } // namespace v8::internal
|
||||||
|
|
||||||
#endif // V8_FUNC_NAME_INFERRER_H_
|
#endif // V8_FUNC_NAME_INFERRER_H_
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
#include "bootstrapper.h"
|
#include "bootstrapper.h"
|
||||||
#include "codegen.h"
|
#include "codegen.h"
|
||||||
#include "compiler.h"
|
#include "compiler.h"
|
||||||
|
#include "func-name-inferrer.h"
|
||||||
#include "messages.h"
|
#include "messages.h"
|
||||||
#include "parser.h"
|
#include "parser.h"
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
@ -154,6 +155,7 @@ class Parser {
|
|||||||
bool is_pre_parsing_;
|
bool is_pre_parsing_;
|
||||||
ScriptDataImpl* pre_data_;
|
ScriptDataImpl* pre_data_;
|
||||||
bool seen_loop_stmt_; // Used for inner loop detection.
|
bool seen_loop_stmt_; // Used for inner loop detection.
|
||||||
|
FuncNameInferrer* fni_;
|
||||||
|
|
||||||
bool inside_with() const { return with_nesting_level_ > 0; }
|
bool inside_with() const { return with_nesting_level_ > 0; }
|
||||||
ParserFactory* factory() const { return factory_; }
|
ParserFactory* factory() const { return factory_; }
|
||||||
@ -1214,7 +1216,8 @@ Parser::Parser(Handle<Script> script,
|
|||||||
log_(log),
|
log_(log),
|
||||||
is_pre_parsing_(is_pre_parsing == PREPARSE),
|
is_pre_parsing_(is_pre_parsing == PREPARSE),
|
||||||
pre_data_(pre_data),
|
pre_data_(pre_data),
|
||||||
seen_loop_stmt_(false) {
|
seen_loop_stmt_(false),
|
||||||
|
fni_(NULL) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1243,6 +1246,7 @@ FunctionLiteral* Parser::ParseProgram(Handle<String> source,
|
|||||||
|
|
||||||
HistogramTimerScope timer(&Counters::parse);
|
HistogramTimerScope timer(&Counters::parse);
|
||||||
Counters::total_parse_size.Increment(source->length());
|
Counters::total_parse_size.Increment(source->length());
|
||||||
|
fni_ = new FuncNameInferrer();
|
||||||
|
|
||||||
// Initialize parser state.
|
// Initialize parser state.
|
||||||
source->TryFlatten();
|
source->TryFlatten();
|
||||||
@ -1303,6 +1307,9 @@ FunctionLiteral* Parser::ParseLazy(Handle<String> source,
|
|||||||
HistogramTimerScope timer(&Counters::parse_lazy);
|
HistogramTimerScope timer(&Counters::parse_lazy);
|
||||||
Counters::total_parse_size.Increment(source->length());
|
Counters::total_parse_size.Increment(source->length());
|
||||||
|
|
||||||
|
fni_ = new FuncNameInferrer();
|
||||||
|
fni_->PushEnclosingName(name);
|
||||||
|
|
||||||
// Initialize parser state.
|
// Initialize parser state.
|
||||||
source->TryFlatten();
|
source->TryFlatten();
|
||||||
scanner_.Initialize(source, start_position, end_position, JAVASCRIPT);
|
scanner_.Initialize(source, start_position, end_position, JAVASCRIPT);
|
||||||
@ -2080,9 +2087,12 @@ Block* Parser::ParseVariableDeclarations(bool accept_IN,
|
|||||||
VariableProxy* last_var = NULL; // the last variable declared
|
VariableProxy* last_var = NULL; // the last variable declared
|
||||||
int nvars = 0; // the number of variables declared
|
int nvars = 0; // the number of variables declared
|
||||||
do {
|
do {
|
||||||
|
if (fni_ != NULL) fni_->Enter();
|
||||||
|
|
||||||
// Parse variable name.
|
// Parse variable name.
|
||||||
if (nvars > 0) Consume(Token::COMMA);
|
if (nvars > 0) Consume(Token::COMMA);
|
||||||
Handle<String> name = ParseIdentifier(CHECK_OK);
|
Handle<String> name = ParseIdentifier(CHECK_OK);
|
||||||
|
if (fni_ != NULL) fni_->PushVariableName(name);
|
||||||
|
|
||||||
// Declare variable.
|
// Declare variable.
|
||||||
// Note that we *always* must treat the initial value via a separate init
|
// Note that we *always* must treat the initial value via a separate init
|
||||||
@ -2134,6 +2144,8 @@ Block* Parser::ParseVariableDeclarations(bool accept_IN,
|
|||||||
Expect(Token::ASSIGN, CHECK_OK);
|
Expect(Token::ASSIGN, CHECK_OK);
|
||||||
position = scanner().location().beg_pos;
|
position = scanner().location().beg_pos;
|
||||||
value = ParseAssignmentExpression(accept_IN, CHECK_OK);
|
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
|
// Make sure that 'const c' actually initializes 'c' to undefined
|
||||||
@ -2210,6 +2222,8 @@ Block* Parser::ParseVariableDeclarations(bool accept_IN,
|
|||||||
Assignment* assignment = NEW(Assignment(op, last_var, value, position));
|
Assignment* assignment = NEW(Assignment(op, last_var, value, position));
|
||||||
if (block) block->AddStatement(NEW(ExpressionStatement(assignment)));
|
if (block) block->AddStatement(NEW(ExpressionStatement(assignment)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fni_ != NULL) fni_->Leave();
|
||||||
} while (peek() == Token::COMMA);
|
} while (peek() == Token::COMMA);
|
||||||
|
|
||||||
if (!is_const && nvars == 1) {
|
if (!is_const && nvars == 1) {
|
||||||
@ -2822,9 +2836,11 @@ Expression* Parser::ParseAssignmentExpression(bool accept_IN, bool* ok) {
|
|||||||
// ConditionalExpression
|
// ConditionalExpression
|
||||||
// LeftHandSideExpression AssignmentOperator AssignmentExpression
|
// LeftHandSideExpression AssignmentOperator AssignmentExpression
|
||||||
|
|
||||||
|
if (fni_ != NULL) fni_->Enter();
|
||||||
Expression* expression = ParseConditionalExpression(accept_IN, CHECK_OK);
|
Expression* expression = ParseConditionalExpression(accept_IN, CHECK_OK);
|
||||||
|
|
||||||
if (!Token::IsAssignmentOp(peek())) {
|
if (!Token::IsAssignmentOp(peek())) {
|
||||||
|
if (fni_ != NULL) fni_->Leave();
|
||||||
// Parsed conditional expression only (no assignment).
|
// Parsed conditional expression only (no assignment).
|
||||||
return expression;
|
return expression;
|
||||||
}
|
}
|
||||||
@ -2855,6 +2871,19 @@ Expression* Parser::ParseAssignmentExpression(bool accept_IN, bool* ok) {
|
|||||||
temp_scope_->AddProperty();
|
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));
|
return NEW(Assignment(op, expression, right, pos));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3125,6 +3154,7 @@ Expression* Parser::ParseLeftHandSideExpression(bool* ok) {
|
|||||||
int pos = scanner().location().beg_pos;
|
int pos = scanner().location().beg_pos;
|
||||||
Handle<String> name = ParseIdentifierName(CHECK_OK);
|
Handle<String> name = ParseIdentifierName(CHECK_OK);
|
||||||
result = factory()->NewProperty(result, NEW(Literal(name)), pos);
|
result = factory()->NewProperty(result, NEW(Literal(name)), pos);
|
||||||
|
if (fni_ != NULL) fni_->PushLiteralName(name);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3211,6 +3241,7 @@ Expression* Parser::ParseMemberWithNewPrefixesExpression(PositionStack* stack,
|
|||||||
int pos = scanner().location().beg_pos;
|
int pos = scanner().location().beg_pos;
|
||||||
Handle<String> name = ParseIdentifierName(CHECK_OK);
|
Handle<String> name = ParseIdentifierName(CHECK_OK);
|
||||||
result = factory()->NewProperty(result, NEW(Literal(name)), pos);
|
result = factory()->NewProperty(result, NEW(Literal(name)), pos);
|
||||||
|
if (fni_ != NULL) fni_->PushLiteralName(name);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Token::LPAREN: {
|
case Token::LPAREN: {
|
||||||
@ -3321,6 +3352,7 @@ Expression* Parser::ParsePrimaryExpression(bool* ok) {
|
|||||||
|
|
||||||
case Token::IDENTIFIER: {
|
case Token::IDENTIFIER: {
|
||||||
Handle<String> name = ParseIdentifier(CHECK_OK);
|
Handle<String> name = ParseIdentifier(CHECK_OK);
|
||||||
|
if (fni_ != NULL) fni_->PushVariableName(name);
|
||||||
if (is_pre_parsing_) {
|
if (is_pre_parsing_) {
|
||||||
result = VariableProxySentinel::identifier_proxy();
|
result = VariableProxySentinel::identifier_proxy();
|
||||||
} else {
|
} else {
|
||||||
@ -3343,6 +3375,7 @@ Expression* Parser::ParsePrimaryExpression(bool* ok) {
|
|||||||
factory()->LookupSymbol(scanner_.literal_string(),
|
factory()->LookupSymbol(scanner_.literal_string(),
|
||||||
scanner_.literal_length());
|
scanner_.literal_length());
|
||||||
result = NEW(Literal(symbol));
|
result = NEW(Literal(symbol));
|
||||||
|
if (fni_ != NULL) fni_->PushLiteralName(symbol);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3640,6 +3673,8 @@ Expression* Parser::ParseObjectLiteral(bool* ok) {
|
|||||||
|
|
||||||
Expect(Token::LBRACE, CHECK_OK);
|
Expect(Token::LBRACE, CHECK_OK);
|
||||||
while (peek() != Token::RBRACE) {
|
while (peek() != Token::RBRACE) {
|
||||||
|
if (fni_ != NULL) fni_->Enter();
|
||||||
|
|
||||||
Literal* key = NULL;
|
Literal* key = NULL;
|
||||||
Token::Value next = peek();
|
Token::Value next = peek();
|
||||||
switch (next) {
|
switch (next) {
|
||||||
@ -3648,6 +3683,8 @@ Expression* Parser::ParseObjectLiteral(bool* ok) {
|
|||||||
bool is_setter = false;
|
bool is_setter = false;
|
||||||
Handle<String> id =
|
Handle<String> id =
|
||||||
ParseIdentifierOrGetOrSet(&is_getter, &is_setter, CHECK_OK);
|
ParseIdentifierOrGetOrSet(&is_getter, &is_setter, CHECK_OK);
|
||||||
|
if (fni_ != NULL) fni_->PushLiteralName(id);
|
||||||
|
|
||||||
if ((is_getter || is_setter) && peek() != Token::COLON) {
|
if ((is_getter || is_setter) && peek() != Token::COLON) {
|
||||||
ObjectLiteral::Property* property =
|
ObjectLiteral::Property* property =
|
||||||
ParseObjectLiteralGetSet(is_getter, CHECK_OK);
|
ParseObjectLiteralGetSet(is_getter, CHECK_OK);
|
||||||
@ -3656,6 +3693,11 @@ Expression* Parser::ParseObjectLiteral(bool* ok) {
|
|||||||
}
|
}
|
||||||
properties.Add(property);
|
properties.Add(property);
|
||||||
if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK);
|
if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK);
|
||||||
|
|
||||||
|
if (fni_ != NULL) {
|
||||||
|
fni_->Infer();
|
||||||
|
fni_->Leave();
|
||||||
|
}
|
||||||
continue; // restart the while
|
continue; // restart the while
|
||||||
}
|
}
|
||||||
// Failed to parse as get/set property, so it's just a property
|
// Failed to parse as get/set property, so it's just a property
|
||||||
@ -3668,6 +3710,7 @@ Expression* Parser::ParseObjectLiteral(bool* ok) {
|
|||||||
Handle<String> string =
|
Handle<String> string =
|
||||||
factory()->LookupSymbol(scanner_.literal_string(),
|
factory()->LookupSymbol(scanner_.literal_string(),
|
||||||
scanner_.literal_length());
|
scanner_.literal_length());
|
||||||
|
if (fni_ != NULL) fni_->PushLiteralName(string);
|
||||||
uint32_t index;
|
uint32_t index;
|
||||||
if (!string.is_null() && string->AsArrayIndex(&index)) {
|
if (!string.is_null() && string->AsArrayIndex(&index)) {
|
||||||
key = NewNumberLiteral(index);
|
key = NewNumberLiteral(index);
|
||||||
@ -3711,6 +3754,11 @@ Expression* Parser::ParseObjectLiteral(bool* ok) {
|
|||||||
|
|
||||||
// TODO(1240767): Consider allowing trailing comma.
|
// TODO(1240767): Consider allowing trailing comma.
|
||||||
if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK);
|
if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK);
|
||||||
|
|
||||||
|
if (fni_ != NULL) {
|
||||||
|
fni_->Infer();
|
||||||
|
fni_->Leave();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Expect(Token::RBRACE, CHECK_OK);
|
Expect(Token::RBRACE, CHECK_OK);
|
||||||
// Computation of literal_index must happen before pre parse bailout.
|
// Computation of literal_index must happen before pre parse bailout.
|
||||||
@ -3922,6 +3970,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> var_name,
|
|||||||
// when peeling or unrolling such a loop.
|
// when peeling or unrolling such a loop.
|
||||||
seen_loop_stmt_ = true;
|
seen_loop_stmt_ = true;
|
||||||
|
|
||||||
|
if (fni_ != NULL && !is_named) fni_->AddFunction(function_literal);
|
||||||
return function_literal;
|
return function_literal;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,6 @@
|
|||||||
#include "v8.h"
|
#include "v8.h"
|
||||||
|
|
||||||
#include "ast.h"
|
#include "ast.h"
|
||||||
#include "func-name-inferrer.h"
|
|
||||||
#include "scopes.h"
|
#include "scopes.h"
|
||||||
#include "rewriter.h"
|
#include "rewriter.h"
|
||||||
|
|
||||||
@ -39,10 +38,6 @@ namespace internal {
|
|||||||
class AstOptimizer: public AstVisitor {
|
class AstOptimizer: public AstVisitor {
|
||||||
public:
|
public:
|
||||||
explicit AstOptimizer() : has_function_literal_(false) {}
|
explicit AstOptimizer() : has_function_literal_(false) {}
|
||||||
explicit AstOptimizer(Handle<String> enclosing_name)
|
|
||||||
: has_function_literal_(false) {
|
|
||||||
func_name_inferrer_.PushEnclosingName(enclosing_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Optimize(ZoneList<Statement*>* statements);
|
void Optimize(ZoneList<Statement*>* statements);
|
||||||
|
|
||||||
@ -50,8 +45,6 @@ class AstOptimizer: public AstVisitor {
|
|||||||
// Used for loop condition analysis. Cleared before visiting a loop
|
// Used for loop condition analysis. Cleared before visiting a loop
|
||||||
// condition, set when a function literal is visited.
|
// condition, set when a function literal is visited.
|
||||||
bool has_function_literal_;
|
bool has_function_literal_;
|
||||||
// Helper object for function name inferring.
|
|
||||||
FuncNameInferrer func_name_inferrer_;
|
|
||||||
|
|
||||||
// Helpers
|
// Helpers
|
||||||
void OptimizeArguments(ZoneList<Expression*>* arguments);
|
void OptimizeArguments(ZoneList<Expression*>* arguments);
|
||||||
@ -211,11 +204,6 @@ void AstOptimizer::VisitDebuggerStatement(DebuggerStatement* node) {
|
|||||||
|
|
||||||
void AstOptimizer::VisitFunctionLiteral(FunctionLiteral* node) {
|
void AstOptimizer::VisitFunctionLiteral(FunctionLiteral* node) {
|
||||||
has_function_literal_ = true;
|
has_function_literal_ = true;
|
||||||
|
|
||||||
if (node->name()->length() == 0) {
|
|
||||||
// Anonymous function.
|
|
||||||
func_name_inferrer_.AddFunction(node);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -247,11 +235,6 @@ void AstOptimizer::VisitVariableProxy(VariableProxy* node) {
|
|||||||
var->type()->SetAsLikelySmi();
|
var->type()->SetAsLikelySmi();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!var->is_this() &&
|
|
||||||
!Heap::result_symbol()->Equals(*var->name())) {
|
|
||||||
func_name_inferrer_.PushName(var->name());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FLAG_safe_int32_compiler) {
|
if (FLAG_safe_int32_compiler) {
|
||||||
if (var->IsStackAllocated() &&
|
if (var->IsStackAllocated() &&
|
||||||
!var->is_arguments() &&
|
!var->is_arguments() &&
|
||||||
@ -268,11 +251,6 @@ void AstOptimizer::VisitLiteral(Literal* node) {
|
|||||||
if (literal->IsSmi()) {
|
if (literal->IsSmi()) {
|
||||||
node->type()->SetAsLikelySmi();
|
node->type()->SetAsLikelySmi();
|
||||||
node->set_side_effect_free(true);
|
node->set_side_effect_free(true);
|
||||||
} else if (literal->IsString()) {
|
|
||||||
Handle<String> lit_str(Handle<String>::cast(literal));
|
|
||||||
if (!Heap::prototype_symbol()->Equals(*lit_str)) {
|
|
||||||
func_name_inferrer_.PushName(lit_str);
|
|
||||||
}
|
|
||||||
} else if (literal->IsHeapNumber()) {
|
} else if (literal->IsHeapNumber()) {
|
||||||
if (node->to_int32()) {
|
if (node->to_int32()) {
|
||||||
// Any HeapNumber has an int32 value if it is the input to a bit op.
|
// Any HeapNumber has an int32 value if it is the input to a bit op.
|
||||||
@ -299,8 +277,6 @@ void AstOptimizer::VisitArrayLiteral(ArrayLiteral* node) {
|
|||||||
|
|
||||||
void AstOptimizer::VisitObjectLiteral(ObjectLiteral* node) {
|
void AstOptimizer::VisitObjectLiteral(ObjectLiteral* node) {
|
||||||
for (int i = 0; i < node->properties()->length(); i++) {
|
for (int i = 0; i < node->properties()->length(); i++) {
|
||||||
ScopedFuncNameInferrer scoped_fni(&func_name_inferrer_);
|
|
||||||
scoped_fni.Enter();
|
|
||||||
Visit(node->properties()->at(i)->key());
|
Visit(node->properties()->at(i)->key());
|
||||||
Visit(node->properties()->at(i)->value());
|
Visit(node->properties()->at(i)->value());
|
||||||
}
|
}
|
||||||
@ -314,17 +290,11 @@ void AstOptimizer::VisitCatchExtensionObject(CatchExtensionObject* node) {
|
|||||||
|
|
||||||
|
|
||||||
void AstOptimizer::VisitAssignment(Assignment* node) {
|
void AstOptimizer::VisitAssignment(Assignment* node) {
|
||||||
ScopedFuncNameInferrer scoped_fni(&func_name_inferrer_);
|
|
||||||
switch (node->op()) {
|
switch (node->op()) {
|
||||||
case Token::INIT_VAR:
|
case Token::INIT_VAR:
|
||||||
case Token::INIT_CONST:
|
case Token::INIT_CONST:
|
||||||
case Token::ASSIGN:
|
case Token::ASSIGN:
|
||||||
// No type can be infered from the general assignment.
|
// No type can be infered from the general assignment.
|
||||||
|
|
||||||
// Don't infer if it is "a = function(){...}();"-like expression.
|
|
||||||
if (node->value()->AsCall() == NULL) {
|
|
||||||
scoped_fni.Enter();
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case Token::ASSIGN_BIT_OR:
|
case Token::ASSIGN_BIT_OR:
|
||||||
case Token::ASSIGN_BIT_XOR:
|
case Token::ASSIGN_BIT_XOR:
|
||||||
@ -430,12 +400,6 @@ void AstOptimizer::VisitCallNew(CallNew* node) {
|
|||||||
|
|
||||||
|
|
||||||
void AstOptimizer::VisitCallRuntime(CallRuntime* node) {
|
void AstOptimizer::VisitCallRuntime(CallRuntime* node) {
|
||||||
ScopedFuncNameInferrer scoped_fni(&func_name_inferrer_);
|
|
||||||
if (Factory::InitializeVarGlobal_symbol()->Equals(*node->name()) &&
|
|
||||||
node->arguments()->length() >= 2 &&
|
|
||||||
node->arguments()->at(1)->AsFunctionLiteral() != NULL) {
|
|
||||||
scoped_fni.Enter();
|
|
||||||
}
|
|
||||||
OptimizeArguments(node->arguments());
|
OptimizeArguments(node->arguments());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1025,7 +989,7 @@ bool Rewriter::Optimize(FunctionLiteral* function) {
|
|||||||
|
|
||||||
if (FLAG_optimize_ast && !body->is_empty()) {
|
if (FLAG_optimize_ast && !body->is_empty()) {
|
||||||
HistogramTimerScope timer(&Counters::ast_optimization);
|
HistogramTimerScope timer(&Counters::ast_optimization);
|
||||||
AstOptimizer optimizer(function->name());
|
AstOptimizer optimizer;
|
||||||
optimizer.Optimize(body);
|
optimizer.Optimize(body);
|
||||||
if (optimizer.HasStackOverflow()) {
|
if (optimizer.HasStackOverflow()) {
|
||||||
return false;
|
return false;
|
||||||
|
Loading…
Reference in New Issue
Block a user