Chromium Code Reviews| Index: src/ast.cc | 
| diff --git a/src/ast.cc b/src/ast.cc | 
| index 811193b49bde08c34da5f54648a90b0542c4ab89..43b9273e10069ccb1a7d94ec6796817e5fad894c 100644 | 
| --- a/src/ast.cc | 
| +++ b/src/ast.cc | 
| @@ -115,7 +115,8 @@ Assignment::Assignment(Isolate* isolate, | 
| Token::Value op, | 
| Expression* target, | 
| Expression* value, | 
| - int pos) | 
| + int pos, | 
| + AstNodeFactory* factory) | 
| : Expression(isolate), | 
| op_(op), | 
| target_(target), | 
| @@ -130,11 +131,7 @@ Assignment::Assignment(Isolate* isolate, | 
| ASSERT(Token::IsAssignmentOp(op)); | 
| if (is_compound()) { | 
| binary_operation_ = | 
| - new(isolate->zone()) BinaryOperation(isolate, | 
| - binary_op(), | 
| - target, | 
| - value, | 
| - pos + 1); | 
| + factory->NewBinaryOperation(binary_op(), target, value, pos + 1); | 
| compound_load_id_ = GetNextId(isolate); | 
| } | 
| } | 
| @@ -179,6 +176,16 @@ LanguageMode FunctionLiteral::language_mode() const { | 
| } | 
| +bool FunctionLiteral::ShouldSelfOptimize() { | 
| + return !ast_properties()->flags()->Contains(kDontSelfOptimize); | 
| +} | 
| + | 
| + | 
| +int FunctionLiteral::AstNodeCount() { | 
| + return ast_properties()->node_count(); | 
| +} | 
| + | 
| + | 
| ObjectLiteral::Property::Property(Literal* key, Expression* value) { | 
| emit_store_ = true; | 
| key_ = key; | 
| @@ -196,10 +203,11 @@ ObjectLiteral::Property::Property(Literal* key, Expression* value) { | 
| } | 
| -ObjectLiteral::Property::Property(bool is_getter, FunctionLiteral* value) { | 
| - Isolate* isolate = Isolate::Current(); | 
| +ObjectLiteral::Property::Property(bool is_getter, | 
| + FunctionLiteral* value, | 
| + AstNodeFactory* factory) { | 
| emit_store_ = true; | 
| - key_ = new(isolate->zone()) Literal(isolate, value->name()); | 
| + key_ = factory->NewLiteral(value->name()); | 
| value_ = value; | 
| kind_ = is_getter ? GETTER : SETTER; | 
| } | 
| @@ -431,223 +439,6 @@ bool Declaration::IsInlineable() const { | 
| } | 
| -bool TargetCollector::IsInlineable() const { | 
| - UNREACHABLE(); | 
| - return false; | 
| -} | 
| - | 
| - | 
| -bool ForInStatement::IsInlineable() const { | 
| - return false; | 
| -} | 
| - | 
| - | 
| -bool WithStatement::IsInlineable() const { | 
| - return false; | 
| -} | 
| - | 
| - | 
| -bool SwitchStatement::IsInlineable() const { | 
| - return false; | 
| -} | 
| - | 
| - | 
| -bool TryStatement::IsInlineable() const { | 
| - return false; | 
| -} | 
| - | 
| - | 
| -bool TryCatchStatement::IsInlineable() const { | 
| - return false; | 
| -} | 
| - | 
| - | 
| -bool TryFinallyStatement::IsInlineable() const { | 
| - return false; | 
| -} | 
| - | 
| - | 
| -bool DebuggerStatement::IsInlineable() const { | 
| - return false; | 
| -} | 
| - | 
| - | 
| -bool Throw::IsInlineable() const { | 
| - return exception()->IsInlineable(); | 
| -} | 
| - | 
| - | 
| -bool MaterializedLiteral::IsInlineable() const { | 
| - // TODO(1322): Allow materialized literals. | 
| - return false; | 
| -} | 
| - | 
| - | 
| -bool FunctionLiteral::IsInlineable() const { | 
| - // TODO(1322): Allow materialized literals. | 
| - return false; | 
| -} | 
| - | 
| - | 
| -bool ThisFunction::IsInlineable() const { | 
| - return true; | 
| -} | 
| - | 
| - | 
| -bool SharedFunctionInfoLiteral::IsInlineable() const { | 
| - return false; | 
| -} | 
| - | 
| - | 
| -bool ForStatement::IsInlineable() const { | 
| - return (init() == NULL || init()->IsInlineable()) | 
| - && (cond() == NULL || cond()->IsInlineable()) | 
| - && (next() == NULL || next()->IsInlineable()) | 
| - && body()->IsInlineable(); | 
| -} | 
| - | 
| - | 
| -bool WhileStatement::IsInlineable() const { | 
| - return cond()->IsInlineable() | 
| - && body()->IsInlineable(); | 
| -} | 
| - | 
| - | 
| -bool DoWhileStatement::IsInlineable() const { | 
| - return cond()->IsInlineable() | 
| - && body()->IsInlineable(); | 
| -} | 
| - | 
| - | 
| -bool ContinueStatement::IsInlineable() const { | 
| - return true; | 
| -} | 
| - | 
| - | 
| -bool BreakStatement::IsInlineable() const { | 
| - return true; | 
| -} | 
| - | 
| - | 
| -bool EmptyStatement::IsInlineable() const { | 
| - return true; | 
| -} | 
| - | 
| - | 
| -bool Literal::IsInlineable() const { | 
| - return true; | 
| -} | 
| - | 
| - | 
| -bool Block::IsInlineable() const { | 
| - const int count = statements_.length(); | 
| - for (int i = 0; i < count; ++i) { | 
| - if (!statements_[i]->IsInlineable()) return false; | 
| - } | 
| - return true; | 
| -} | 
| - | 
| - | 
| -bool ExpressionStatement::IsInlineable() const { | 
| - return expression()->IsInlineable(); | 
| -} | 
| - | 
| - | 
| -bool IfStatement::IsInlineable() const { | 
| - return condition()->IsInlineable() | 
| - && then_statement()->IsInlineable() | 
| - && else_statement()->IsInlineable(); | 
| -} | 
| - | 
| - | 
| -bool ReturnStatement::IsInlineable() const { | 
| - return expression()->IsInlineable(); | 
| -} | 
| - | 
| - | 
| -bool Conditional::IsInlineable() const { | 
| - return condition()->IsInlineable() && then_expression()->IsInlineable() && | 
| - else_expression()->IsInlineable(); | 
| -} | 
| - | 
| - | 
| -bool VariableProxy::IsInlineable() const { | 
| - return var()->IsUnallocated() | 
| - || var()->IsStackAllocated() | 
| - || var()->IsContextSlot(); | 
| -} | 
| - | 
| - | 
| -bool Assignment::IsInlineable() const { | 
| - return target()->IsInlineable() && value()->IsInlineable(); | 
| -} | 
| - | 
| - | 
| -bool Property::IsInlineable() const { | 
| - return obj()->IsInlineable() && key()->IsInlineable(); | 
| -} | 
| - | 
| - | 
| -bool Call::IsInlineable() const { | 
| - if (!expression()->IsInlineable()) return false; | 
| - const int count = arguments()->length(); | 
| - for (int i = 0; i < count; ++i) { | 
| - if (!arguments()->at(i)->IsInlineable()) return false; | 
| - } | 
| - return true; | 
| -} | 
| - | 
| - | 
| -bool CallNew::IsInlineable() const { | 
| - if (!expression()->IsInlineable()) return false; | 
| - const int count = arguments()->length(); | 
| - for (int i = 0; i < count; ++i) { | 
| - if (!arguments()->at(i)->IsInlineable()) return false; | 
| - } | 
| - return true; | 
| -} | 
| - | 
| - | 
| -bool CallRuntime::IsInlineable() const { | 
| - // Don't try to inline JS runtime calls because we don't (currently) even | 
| - // optimize them. | 
| - if (is_jsruntime()) return false; | 
| - // Don't inline the %_ArgumentsLength or %_Arguments because their | 
| - // implementation will not work. There is no stack frame to get them | 
| - // from. | 
| - if (function()->intrinsic_type == Runtime::INLINE && | 
| - (name()->IsEqualTo(CStrVector("_ArgumentsLength")) || | 
| - name()->IsEqualTo(CStrVector("_Arguments")))) { | 
| - return false; | 
| - } | 
| - const int count = arguments()->length(); | 
| - for (int i = 0; i < count; ++i) { | 
| - if (!arguments()->at(i)->IsInlineable()) return false; | 
| - } | 
| - return true; | 
| -} | 
| - | 
| - | 
| -bool UnaryOperation::IsInlineable() const { | 
| - return expression()->IsInlineable(); | 
| -} | 
| - | 
| - | 
| -bool BinaryOperation::IsInlineable() const { | 
| - return left()->IsInlineable() && right()->IsInlineable(); | 
| -} | 
| - | 
| - | 
| -bool CompareOperation::IsInlineable() const { | 
| - return left()->IsInlineable() && right()->IsInlineable(); | 
| -} | 
| - | 
| - | 
| -bool CountOperation::IsInlineable() const { | 
| - return expression()->IsInlineable(); | 
| -} | 
| - | 
| - | 
| // ---------------------------------------------------------------------------- | 
| // Recording of type feedback | 
| @@ -1215,4 +1006,177 @@ CaseClause::CaseClause(Isolate* isolate, | 
| entry_id_(AstNode::GetNextId(isolate)) { | 
| } | 
| + | 
| +AstProperties* AstConstructionVisitor::DetachAstProperties() { | 
| + properties_->add_node_count(node_count_); | 
| + properties_->flags()->Add(flags_); | 
| + return properties_; | 
| +} | 
| + | 
| + | 
| +void AstConstructionVisitor::VisitDeclaration(Declaration* node) { | 
| + increase_node_count(); | 
| + // TODO(jkummerow): Inlineable iff | 
| + // proxy()->var()->IsStackAllocated() && fun() == NULL; | 
| 
 
fschneider
2012/02/06 14:14:29
Forgotten commented code?
 
Jakob Kummerow
2012/02/07 12:38:37
No, two-line comment :-)
It was intended as a remi
 
 | 
| +} | 
| + | 
| + | 
| +#define INCREASE_NODE_COUNT(NodeType) \ | 
| + void AstConstructionVisitor::Visit##NodeType(NodeType* node) { \ | 
| + increase_node_count(); \ | 
| + } | 
| + | 
| +INCREASE_NODE_COUNT(Block) | 
| +INCREASE_NODE_COUNT(ExpressionStatement) | 
| +INCREASE_NODE_COUNT(EmptyStatement) | 
| +INCREASE_NODE_COUNT(IfStatement) | 
| +INCREASE_NODE_COUNT(ContinueStatement) | 
| +INCREASE_NODE_COUNT(BreakStatement) | 
| +INCREASE_NODE_COUNT(ReturnStatement) | 
| +INCREASE_NODE_COUNT(Conditional) | 
| +INCREASE_NODE_COUNT(Literal) | 
| +INCREASE_NODE_COUNT(Assignment) | 
| +INCREASE_NODE_COUNT(Throw) | 
| +INCREASE_NODE_COUNT(Property) | 
| +INCREASE_NODE_COUNT(UnaryOperation) | 
| +INCREASE_NODE_COUNT(CountOperation) | 
| +INCREASE_NODE_COUNT(BinaryOperation) | 
| +INCREASE_NODE_COUNT(CompareOperation) | 
| +INCREASE_NODE_COUNT(ThisFunction) | 
| + | 
| +#undef INCREASE_NODE_COUNT | 
| + | 
| + | 
| +void AstConstructionVisitor::VisitWithStatement(WithStatement* node) { | 
| + increase_node_count(); | 
| + add_flag(kDontCrankshaft); | 
| + add_flag(kDontInline); | 
| +} | 
| + | 
| + | 
| +void AstConstructionVisitor::VisitSwitchStatement(SwitchStatement* node) { | 
| + increase_node_count(); | 
| + add_flag(kDontInline); | 
| +} | 
| + | 
| + | 
| +void AstConstructionVisitor::VisitDoWhileStatement(DoWhileStatement* node) { | 
| + increase_node_count(); | 
| + add_flag(kDontSelfOptimize); | 
| +} | 
| + | 
| + | 
| +void AstConstructionVisitor::VisitWhileStatement(WhileStatement* node) { | 
| + increase_node_count(); | 
| + add_flag(kDontSelfOptimize); | 
| +} | 
| + | 
| + | 
| +void AstConstructionVisitor::VisitForStatement(ForStatement* node) { | 
| + increase_node_count(); | 
| + add_flag(kDontSelfOptimize); | 
| +} | 
| + | 
| + | 
| +void AstConstructionVisitor::VisitForInStatement(ForInStatement* node) { | 
| + increase_node_count(); | 
| + add_flag(kDontCrankshaft); | 
| + add_flag(kDontInline); | 
| + add_flag(kDontSelfOptimize); | 
| +} | 
| + | 
| + | 
| +void AstConstructionVisitor::VisitTryCatchStatement(TryCatchStatement* node) { | 
| + increase_node_count(); | 
| + add_flag(kDontCrankshaft); | 
| + add_flag(kDontInline); | 
| +} | 
| + | 
| + | 
| +void AstConstructionVisitor::VisitTryFinallyStatement( | 
| + TryFinallyStatement* node) { | 
| + increase_node_count(); | 
| + add_flag(kDontCrankshaft); | 
| + add_flag(kDontInline); | 
| +} | 
| + | 
| + | 
| +void AstConstructionVisitor::VisitDebuggerStatement(DebuggerStatement* node) { | 
| + increase_node_count(); | 
| + add_flag(kDontCrankshaft); | 
| + add_flag(kDontInline); | 
| +} | 
| + | 
| + | 
| +void AstConstructionVisitor::VisitFunctionLiteral(FunctionLiteral* node) { | 
| + increase_node_count(); | 
| + add_flag(kDontInline); | 
| +} | 
| + | 
| + | 
| +void AstConstructionVisitor::VisitSharedFunctionInfoLiteral( | 
| + SharedFunctionInfoLiteral* node) { | 
| + increase_node_count(); | 
| + add_flag(kDontCrankshaft); | 
| + add_flag(kDontInline); | 
| +} | 
| + | 
| + | 
| +void AstConstructionVisitor::VisitVariableProxy(VariableProxy* node) { | 
| + increase_node_count(); | 
| + // In theory, we'd have to add: | 
| + // if(node->var()->IsLookupSlot()) { add_flag(kDontInline); } | 
| + // However, node->var() is usually not bound yet at VariableProxy creation | 
| + // time, and LOOKUP variables only result from constructs that cannot | 
| + // be inlined anyway. | 
| +} | 
| + | 
| + | 
| +void AstConstructionVisitor::VisitRegExpLiteral(RegExpLiteral* node) { | 
| + increase_node_count(); | 
| + add_flag(kDontInline); // TODO(1322): Allow materialized literals. | 
| +} | 
| + | 
| + | 
| +void AstConstructionVisitor::VisitObjectLiteral(ObjectLiteral* node) { | 
| + increase_node_count(); | 
| + add_flag(kDontInline); // TODO(1322): Allow materialized literals. | 
| +} | 
| + | 
| + | 
| +void AstConstructionVisitor::VisitArrayLiteral(ArrayLiteral* node) { | 
| + increase_node_count(); | 
| + add_flag(kDontInline); // TODO(1322): Allow materialized literals. | 
| +} | 
| + | 
| + | 
| +void AstConstructionVisitor::VisitCall(Call* node) { | 
| + increase_node_count(); | 
| + add_flag(kDontSelfOptimize); | 
| +} | 
| + | 
| + | 
| +void AstConstructionVisitor::VisitCallNew(CallNew* node) { | 
| + increase_node_count(); | 
| + add_flag(kDontSelfOptimize); | 
| +} | 
| + | 
| + | 
| +void AstConstructionVisitor::VisitCallRuntime(CallRuntime* node) { | 
| + increase_node_count(); | 
| + add_flag(kDontSelfOptimize); | 
| + if (node->is_jsruntime()) { | 
| + // Don't try to inline JS runtime calls because we don't (currently) even | 
| + // optimize them. | 
| + add_flag(kDontInline); | 
| + } else if (node->function()->intrinsic_type == Runtime::INLINE && | 
| + (node->name()->IsEqualTo(CStrVector("_ArgumentsLength")) || | 
| + node->name()->IsEqualTo(CStrVector("_Arguments")))) { | 
| + // Don't inline the %_ArgumentsLength or %_Arguments because their | 
| + // implementation will not work. There is no stack frame to get them | 
| + // from. | 
| + add_flag(kDontInline); | 
| + } | 
| +} | 
| + | 
| } } // namespace v8::internal |