| Index: src/ast.cc
|
| diff --git a/src/ast.cc b/src/ast.cc
|
| index 6af15258a2f898db7b8c6ab67a72190215569e76..9bcc977c4d0a8a5f124eb9d9568e3aeefa688774 100644
|
| --- a/src/ast.cc
|
| +++ b/src/ast.cc
|
| @@ -171,6 +171,28 @@ StrictModeFlag FunctionLiteral::strict_mode_flag() const {
|
| return scope()->strict_mode_flag();
|
| }
|
|
|
| +void FunctionLiteral::ComputeAstNodeCountAndInlineableFlags() {
|
| + is_function_inlineable_ = false;
|
| + is_function_primitive_ = true;
|
| + // All declarations must be inlineable.
|
| + ZoneList<Declaration*>* decls = scope()->declarations();
|
| + int decl_count = decls->length();
|
| + for (int i = 0; i < decl_count; ++i) {
|
| + if (!decls->at(i)->IsInlineable(this)) {
|
| + is_function_primitive_ = false;
|
| + return;
|
| + }
|
| + }
|
| + // All statements in the body must be inlineable.
|
| + for (int i = 0, count = body()->length(); i < count; ++i) {
|
| + if (!body()->at(i)->IsInlineable(this)) {
|
| + is_function_primitive_ = false;
|
| + return;
|
| + }
|
| + }
|
| + is_function_inlineable_ = true;
|
| +}
|
| +
|
|
|
| ObjectLiteral::Property::Property(Literal* key, Expression* value) {
|
| emit_store_ = true;
|
| @@ -419,189 +441,221 @@ bool CompareOperation::IsLiteralCompareNull(Expression** expr) {
|
| // ----------------------------------------------------------------------------
|
| // Inlining support
|
|
|
| -bool Declaration::IsInlineable() const {
|
| - return proxy()->var()->IsStackAllocated() && fun() == NULL;
|
| +bool Declaration::IsInlineable(FunctionLiteral* function) const {
|
| + function->increment_ast_node_count();
|
| + return (proxy()->var()->IsStackAllocated() && fun() == NULL);
|
| }
|
|
|
|
|
| -bool TargetCollector::IsInlineable() const {
|
| +bool TargetCollector::IsInlineable(FunctionLiteral* function) const {
|
| UNREACHABLE();
|
| return false;
|
| }
|
|
|
|
|
| -bool ForInStatement::IsInlineable() const {
|
| +bool ForInStatement::IsInlineable(FunctionLiteral* function) const {
|
| return false;
|
| }
|
|
|
|
|
| -bool WithStatement::IsInlineable() const {
|
| +bool WithStatement::IsInlineable(FunctionLiteral* function) const {
|
| return false;
|
| }
|
|
|
|
|
| -bool SwitchStatement::IsInlineable() const {
|
| +bool SwitchStatement::IsInlineable(FunctionLiteral* function) const {
|
| return false;
|
| }
|
|
|
|
|
| -bool TryStatement::IsInlineable() const {
|
| +bool TryStatement::IsInlineable(FunctionLiteral* function) const {
|
| return false;
|
| }
|
|
|
|
|
| -bool TryCatchStatement::IsInlineable() const {
|
| +bool TryCatchStatement::IsInlineable(FunctionLiteral* function) const {
|
| return false;
|
| }
|
|
|
|
|
| -bool TryFinallyStatement::IsInlineable() const {
|
| +bool TryFinallyStatement::IsInlineable(FunctionLiteral* function) const {
|
| return false;
|
| }
|
|
|
|
|
| -bool DebuggerStatement::IsInlineable() const {
|
| +bool DebuggerStatement::IsInlineable(FunctionLiteral* function) const {
|
| return false;
|
| }
|
|
|
|
|
| -bool Throw::IsInlineable() const {
|
| - return exception()->IsInlineable();
|
| +bool Throw::IsInlineable(FunctionLiteral* function) const {
|
| + function->increment_ast_node_count();
|
| + return exception()->IsInlineable(function);
|
| }
|
|
|
|
|
| -bool MaterializedLiteral::IsInlineable() const {
|
| +bool MaterializedLiteral::IsInlineable(FunctionLiteral* function) const {
|
| // TODO(1322): Allow materialized literals.
|
| return false;
|
| }
|
|
|
|
|
| -bool FunctionLiteral::IsInlineable() const {
|
| +bool FunctionLiteral::IsInlineable(FunctionLiteral* function) const {
|
| // TODO(1322): Allow materialized literals.
|
| return false;
|
| }
|
|
|
|
|
| -bool ThisFunction::IsInlineable() const {
|
| +bool ThisFunction::IsInlineable(FunctionLiteral* function) const {
|
| + function->increment_ast_node_count();
|
| return true;
|
| }
|
|
|
|
|
| -bool SharedFunctionInfoLiteral::IsInlineable() const {
|
| +bool SharedFunctionInfoLiteral::IsInlineable(FunctionLiteral* function) const {
|
| return false;
|
| }
|
|
|
|
|
| -bool ForStatement::IsInlineable() const {
|
| - return (init() == NULL || init()->IsInlineable())
|
| - && (cond() == NULL || cond()->IsInlineable())
|
| - && (next() == NULL || next()->IsInlineable())
|
| - && body()->IsInlineable();
|
| +bool ForStatement::IsInlineable(FunctionLiteral* function) const {
|
| + function->mark_as_not_primitive();
|
| + function->increment_ast_node_count();
|
| + return (init() == NULL || init()->IsInlineable(function))
|
| + && (cond() == NULL || cond()->IsInlineable(function))
|
| + && (next() == NULL || next()->IsInlineable(function))
|
| + && body()->IsInlineable(function);
|
| }
|
|
|
|
|
| -bool WhileStatement::IsInlineable() const {
|
| - return cond()->IsInlineable()
|
| - && body()->IsInlineable();
|
| +bool WhileStatement::IsInlineable(FunctionLiteral* function) const {
|
| + function->mark_as_not_primitive();
|
| + function->increment_ast_node_count();
|
| + return cond()->IsInlineable(function)
|
| + && body()->IsInlineable(function);
|
| }
|
|
|
|
|
| -bool DoWhileStatement::IsInlineable() const {
|
| - return cond()->IsInlineable()
|
| - && body()->IsInlineable();
|
| +bool DoWhileStatement::IsInlineable(FunctionLiteral* function) const {
|
| + function->mark_as_not_primitive();
|
| + function->increment_ast_node_count();
|
| + return cond()->IsInlineable(function)
|
| + && body()->IsInlineable(function);
|
| }
|
|
|
|
|
| -bool ContinueStatement::IsInlineable() const {
|
| +bool ContinueStatement::IsInlineable(FunctionLiteral* function) const {
|
| + function->increment_ast_node_count();
|
| return true;
|
| }
|
|
|
|
|
| -bool BreakStatement::IsInlineable() const {
|
| +bool BreakStatement::IsInlineable(FunctionLiteral* function) const {
|
| + function->increment_ast_node_count();
|
| return true;
|
| }
|
|
|
|
|
| -bool EmptyStatement::IsInlineable() const {
|
| +bool EmptyStatement::IsInlineable(FunctionLiteral* function) const {
|
| + function->increment_ast_node_count();
|
| return true;
|
| }
|
|
|
|
|
| -bool Literal::IsInlineable() const {
|
| +bool Literal::IsInlineable(FunctionLiteral* function) const {
|
| + function->increment_ast_node_count();
|
| return true;
|
| }
|
|
|
|
|
| -bool Block::IsInlineable() const {
|
| +bool Block::IsInlineable(FunctionLiteral* function) const {
|
| + function->increment_ast_node_count();
|
| const int count = statements_.length();
|
| for (int i = 0; i < count; ++i) {
|
| - if (!statements_[i]->IsInlineable()) return false;
|
| + if (!statements_[i]->IsInlineable(function)) return false;
|
| }
|
| return true;
|
| }
|
|
|
|
|
| -bool ExpressionStatement::IsInlineable() const {
|
| - return expression()->IsInlineable();
|
| +bool ExpressionStatement::IsInlineable(FunctionLiteral* function) const {
|
| + function->increment_ast_node_count();
|
| + return expression()->IsInlineable(function);
|
| }
|
|
|
|
|
| -bool IfStatement::IsInlineable() const {
|
| - return condition()->IsInlineable()
|
| - && then_statement()->IsInlineable()
|
| - && else_statement()->IsInlineable();
|
| +bool IfStatement::IsInlineable(FunctionLiteral* function) const {
|
| + function->increment_ast_node_count();
|
| + return condition()->IsInlineable(function)
|
| + && then_statement()->IsInlineable(function)
|
| + && else_statement()->IsInlineable(function);
|
| }
|
|
|
|
|
| -bool ReturnStatement::IsInlineable() const {
|
| - return expression()->IsInlineable();
|
| +bool ReturnStatement::IsInlineable(FunctionLiteral* function) const {
|
| + function->increment_ast_node_count();
|
| + return expression()->IsInlineable(function);
|
| }
|
|
|
|
|
| -bool Conditional::IsInlineable() const {
|
| - return condition()->IsInlineable() && then_expression()->IsInlineable() &&
|
| - else_expression()->IsInlineable();
|
| +bool Conditional::IsInlineable(FunctionLiteral* function) const {
|
| + function->increment_ast_node_count();
|
| + return condition()->IsInlineable(function)
|
| + && then_expression()->IsInlineable(function)
|
| + && else_expression()->IsInlineable(function);
|
| }
|
|
|
|
|
| -bool VariableProxy::IsInlineable() const {
|
| +bool VariableProxy::IsInlineable(FunctionLiteral* function) const {
|
| + function->increment_ast_node_count();
|
| return var()->IsUnallocated()
|
| || var()->IsStackAllocated()
|
| || var()->IsContextSlot();
|
| }
|
|
|
|
|
| -bool Assignment::IsInlineable() const {
|
| - return target()->IsInlineable() && value()->IsInlineable();
|
| +bool Assignment::IsInlineable(FunctionLiteral* function) const {
|
| + function->increment_ast_node_count();
|
| + return target()->IsInlineable(function)
|
| + && value()->IsInlineable(function);
|
| }
|
|
|
|
|
| -bool Property::IsInlineable() const {
|
| - return obj()->IsInlineable() && key()->IsInlineable();
|
| +bool Property::IsInlineable(FunctionLiteral* function) const {
|
| + function->increment_ast_node_count();
|
| + return obj()->IsInlineable(function)
|
| + && key()->IsInlineable(function);
|
| }
|
|
|
|
|
| -bool Call::IsInlineable() const {
|
| - if (!expression()->IsInlineable()) return false;
|
| +bool Call::IsInlineable(FunctionLiteral* function) const {
|
| + function->increment_ast_node_count();
|
| + function->mark_as_not_primitive();
|
| + if (!expression()->IsInlineable(function)) return false;
|
| const int count = arguments()->length();
|
| for (int i = 0; i < count; ++i) {
|
| - if (!arguments()->at(i)->IsInlineable()) return false;
|
| + if (!arguments()->at(i)->IsInlineable(function)) {
|
| + return false;
|
| + }
|
| }
|
| return true;
|
| }
|
|
|
|
|
| -bool CallNew::IsInlineable() const {
|
| - if (!expression()->IsInlineable()) return false;
|
| +bool CallNew::IsInlineable(FunctionLiteral* function) const {
|
| + function->increment_ast_node_count();
|
| + function->mark_as_not_primitive();
|
| + if (!expression()->IsInlineable(function)) return false;
|
| const int count = arguments()->length();
|
| for (int i = 0; i < count; ++i) {
|
| - if (!arguments()->at(i)->IsInlineable()) return false;
|
| + if (!arguments()->at(i)->IsInlineable(function)) {
|
| + return false;
|
| + }
|
| }
|
| return true;
|
| }
|
|
|
|
|
| -bool CallRuntime::IsInlineable() const {
|
| +bool CallRuntime::IsInlineable(FunctionLiteral* function_literal) const {
|
| // Don't try to inline JS runtime calls because we don't (currently) even
|
| // optimize them.
|
| if (is_jsruntime()) return false;
|
| @@ -613,31 +667,41 @@ bool CallRuntime::IsInlineable() const {
|
| name()->IsEqualTo(CStrVector("_Arguments")))) {
|
| return false;
|
| }
|
| + function_literal->increment_ast_node_count();
|
| + function_literal->mark_as_not_primitive();
|
| const int count = arguments()->length();
|
| for (int i = 0; i < count; ++i) {
|
| - if (!arguments()->at(i)->IsInlineable()) return false;
|
| + if (!arguments()->at(i)->IsInlineable(function_literal)) {
|
| + return false;
|
| + }
|
| }
|
| return true;
|
| }
|
|
|
|
|
| -bool UnaryOperation::IsInlineable() const {
|
| - return expression()->IsInlineable();
|
| +bool UnaryOperation::IsInlineable(FunctionLiteral* function) const {
|
| + function->increment_ast_node_count();
|
| + return expression()->IsInlineable(function);
|
| }
|
|
|
|
|
| -bool BinaryOperation::IsInlineable() const {
|
| - return left()->IsInlineable() && right()->IsInlineable();
|
| +bool BinaryOperation::IsInlineable(FunctionLiteral* function) const {
|
| + function->increment_ast_node_count();
|
| + return left()->IsInlineable(function)
|
| + && right()->IsInlineable(function);
|
| }
|
|
|
|
|
| -bool CompareOperation::IsInlineable() const {
|
| - return left()->IsInlineable() && right()->IsInlineable();
|
| +bool CompareOperation::IsInlineable(FunctionLiteral* function) const {
|
| + function->increment_ast_node_count();
|
| + return left()->IsInlineable(function)
|
| + && right()->IsInlineable(function);
|
| }
|
|
|
|
|
| -bool CountOperation::IsInlineable() const {
|
| - return expression()->IsInlineable();
|
| +bool CountOperation::IsInlineable(FunctionLiteral* function) const {
|
| + function->increment_ast_node_count();
|
| + return expression()->IsInlineable(function);
|
| }
|
|
|
|
|
|
|