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 |