| Index: src/ast.cc
|
| diff --git a/src/ast.cc b/src/ast.cc
|
| index 811193b49bde08c34da5f54648a90b0542c4ab89..6427440a55e440cb5425f5a956e8433d85a382af 100644
|
| --- a/src/ast.cc
|
| +++ b/src/ast.cc
|
| @@ -126,18 +126,7 @@ Assignment::Assignment(Isolate* isolate,
|
| assignment_id_(GetNextId(isolate)),
|
| block_start_(false),
|
| block_end_(false),
|
| - is_monomorphic_(false) {
|
| - ASSERT(Token::IsAssignmentOp(op));
|
| - if (is_compound()) {
|
| - binary_operation_ =
|
| - new(isolate->zone()) BinaryOperation(isolate,
|
| - binary_op(),
|
| - target,
|
| - value,
|
| - pos + 1);
|
| - compound_load_id_ = GetNextId(isolate);
|
| - }
|
| -}
|
| + is_monomorphic_(false) { }
|
|
|
|
|
| Token::Value Assignment::binary_op() const {
|
| @@ -179,6 +168,11 @@ LanguageMode FunctionLiteral::language_mode() const {
|
| }
|
|
|
|
|
| +bool FunctionLiteral::ShouldSelfOptimize() {
|
| + return !flags()->Contains(kDontSelfOptimize);
|
| +}
|
| +
|
| +
|
| ObjectLiteral::Property::Property(Literal* key, Expression* value) {
|
| emit_store_ = true;
|
| key_ = key;
|
| @@ -197,9 +191,7 @@ ObjectLiteral::Property::Property(Literal* key, Expression* value) {
|
|
|
|
|
| ObjectLiteral::Property::Property(bool is_getter, FunctionLiteral* value) {
|
| - Isolate* isolate = Isolate::Current();
|
| emit_store_ = true;
|
| - key_ = new(isolate->zone()) Literal(isolate, value->name());
|
| value_ = value;
|
| kind_ = is_getter ? GETTER : SETTER;
|
| }
|
| @@ -431,223 +423,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 +990,164 @@ CaseClause::CaseClause(Isolate* isolate,
|
| entry_id_(AstNode::GetNextId(isolate)) {
|
| }
|
|
|
| +
|
| +#define INCREASE_NODE_COUNT(NodeType) \
|
| + void AstConstructionVisitor::Visit##NodeType(NodeType* node) { \
|
| + increase_node_count(); \
|
| + }
|
| +
|
| +INCREASE_NODE_COUNT(Declaration)
|
| +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
|
|
|