| Index: src/ast.cc
|
| diff --git a/src/ast.cc b/src/ast.cc
|
| index 2e26999c8cf177d4383d9429f3f51416e4d2d78a..affa704e906c280a049e2b3cd7c58d939de9b1c9 100644
|
| --- a/src/ast.cc
|
| +++ b/src/ast.cc
|
| @@ -1,4 +1,4 @@
|
| -// Copyright 2011 the V8 project authors. All rights reserved.
|
| +// Copyright 2012 the V8 project authors. All rights reserved.
|
| // Redistribution and use in source and binary forms, with or without
|
| // modification, are permitted provided that the following conditions are
|
| // met:
|
| @@ -174,6 +174,24 @@ LanguageMode FunctionLiteral::language_mode() const {
|
| }
|
|
|
|
|
| +bool FunctionLiteral::ShouldSelfOptimize() {
|
| + AstNodeType::Flag types = 0;
|
| + int node_count = 0;
|
| + CollectInfo(&types, &node_count);
|
| + return (types & (AstNodeType::kContainsBackEdgesMask |
|
| + AstNodeType::kContainsCallsMask |
|
| + AstNodeType::kPreventsOptimizationMask)) == 0;
|
| +}
|
| +
|
| +
|
| +int FunctionLiteral::AstNodeCount() {
|
| + AstNodeType::Flag types = 0;
|
| + int node_count = 0;
|
| + CollectInfo(&types, &node_count);
|
| + return node_count;
|
| +}
|
| +
|
| +
|
| ObjectLiteral::Property::Property(Literal* key, Expression* value) {
|
| emit_store_ = true;
|
| key_ = key;
|
| @@ -426,6 +444,13 @@ bool Declaration::IsInlineable() const {
|
| }
|
|
|
|
|
| +void Declaration::CollectInfo(AstNodeType::Flag* flags,
|
| + int* node_count) const {
|
| + proxy()->CollectInfo(flags, node_count);
|
| + *node_count += 1;
|
| +}
|
| +
|
| +
|
| bool TargetCollector::IsInlineable() const {
|
| UNREACHABLE();
|
| return false;
|
| @@ -437,28 +462,72 @@ bool ForInStatement::IsInlineable() const {
|
| }
|
|
|
|
|
| +void ForInStatement::CollectInfo(AstNodeType::Flag* flags,
|
| + int* node_count) const {
|
| + *flags |= AstNodeType::kForInStatementMask;
|
| + each()->CollectInfo(flags, node_count);
|
| + enumerable()->CollectInfo(flags, node_count);
|
| + body()->CollectInfo(flags, node_count);
|
| + *node_count += 1;
|
| +}
|
| +
|
| +
|
| bool WithStatement::IsInlineable() const {
|
| return false;
|
| }
|
|
|
|
|
| +void WithStatement::CollectInfo(AstNodeType::Flag* flags,
|
| + int* node_count) const {
|
| + *flags |= AstNodeType::kWithStatementMask;
|
| + expression()->CollectInfo(flags, node_count);
|
| + statement()->CollectInfo(flags, node_count);
|
| + *node_count += 1;
|
| +}
|
| +
|
| +
|
| bool SwitchStatement::IsInlineable() const {
|
| return false;
|
| }
|
|
|
|
|
| +void SwitchStatement::CollectInfo(AstNodeType::Flag* flags,
|
| + int* node_count) const {
|
| + *flags |= AstNodeType::kSwitchStatementMask;
|
| + tag()->CollectInfo(flags, node_count);
|
| + for (int i = 0; i < cases()->length(); ++i) {
|
| + CaseClause* clause(cases()->at(i));
|
| + if (!clause->is_default()) {
|
| + clause->label()->CollectInfo(flags, node_count);
|
| + }
|
| + for (int j = 0; j < clause->statements()->length(); ++j) {
|
| + clause->statements()->at(j)->CollectInfo(flags, node_count);
|
| + }
|
| + }
|
| + *node_count += 1;
|
| +}
|
| +
|
| +
|
| bool TryStatement::IsInlineable() const {
|
| return false;
|
| }
|
|
|
|
|
| -bool TryCatchStatement::IsInlineable() const {
|
| - return false;
|
| +void TryCatchStatement::CollectInfo(AstNodeType::Flag* flags,
|
| + int* node_count) const {
|
| + *flags |= AstNodeType::kTryCatchStatementMask;
|
| + try_block()->CollectInfo(flags, node_count);
|
| + catch_block()->CollectInfo(flags, node_count);
|
| + *node_count += 1;
|
| }
|
|
|
|
|
| -bool TryFinallyStatement::IsInlineable() const {
|
| - return false;
|
| +void TryFinallyStatement::CollectInfo(AstNodeType::Flag* flags,
|
| + int* node_count) const {
|
| + *flags |= AstNodeType::kTryFinallyStatementMask;
|
| + try_block()->CollectInfo(flags, node_count);
|
| + finally_block()->CollectInfo(flags, node_count);
|
| + *node_count += 1;
|
| }
|
|
|
|
|
| @@ -467,33 +536,106 @@ bool DebuggerStatement::IsInlineable() const {
|
| }
|
|
|
|
|
| +void DebuggerStatement::CollectInfo(AstNodeType::Flag* flags,
|
| + int* node_count) const {
|
| + *flags |= AstNodeType::kDebuggerStatementMask;
|
| + *node_count += 1;
|
| +}
|
| +
|
| +
|
| bool Throw::IsInlineable() const {
|
| return exception()->IsInlineable();
|
| }
|
|
|
|
|
| +void Throw::CollectInfo(AstNodeType::Flag* flags, int* node_count) const {
|
| + *flags |= AstNodeType::kThrowMask;
|
| + exception()->CollectInfo(flags, node_count);
|
| + *node_count += 1;
|
| +}
|
| +
|
| +
|
| bool MaterializedLiteral::IsInlineable() const {
|
| // TODO(1322): Allow materialized literals.
|
| return false;
|
| }
|
|
|
|
|
| +void ObjectLiteral::CollectInfo(AstNodeType::Flag* flags,
|
| + int* node_count) const {
|
| + *flags |= AstNodeType::kObjectLiteralMask;
|
| + for (int i = 0; i < properties()->length(); ++i) {
|
| + properties()->at(i)->key()->CollectInfo(flags, node_count);
|
| + properties()->at(i)->value()->CollectInfo(flags, node_count);
|
| + }
|
| + *node_count += 1;
|
| +}
|
| +
|
| +
|
| +void RegExpLiteral::CollectInfo(AstNodeType::Flag* flags,
|
| + int* node_count) const {
|
| + *flags |= AstNodeType::kRegExpLiteralMask;
|
| + *node_count += 1;
|
| +}
|
| +
|
| +
|
| +void ArrayLiteral::CollectInfo(AstNodeType::Flag* flags,
|
| + int* node_count) const {
|
| + *flags |= AstNodeType::kArrayLiteralMask;
|
| + for (int i = 0; i < values()->length(); ++i) {
|
| + values()->at(i)->CollectInfo(flags, node_count);
|
| + }
|
| + *node_count += 1;
|
| +}
|
| +
|
| +
|
| bool FunctionLiteral::IsInlineable() const {
|
| // TODO(1322): Allow materialized literals.
|
| return false;
|
| }
|
|
|
|
|
| +void FunctionLiteral::CollectInfo(AstNodeType::Flag* flags,
|
| + int* node_count) const {
|
| + *flags |= AstNodeType::kFunctionLiteralMask;
|
| + if (scope()->declarations() != NULL) {
|
| + for (int i = 0; i < scope()->declarations()->length(); ++i) {
|
| + scope()->declarations()->at(i)->CollectInfo(flags, node_count);
|
| + }
|
| + }
|
| + if (body() != NULL) {
|
| + for (int i = 0; i < body()->length(); ++i) {
|
| + body()->at(i)->CollectInfo(flags, node_count);
|
| + }
|
| + }
|
| + *node_count += 1;
|
| +}
|
| +
|
| +
|
| bool ThisFunction::IsInlineable() const {
|
| return true;
|
| }
|
|
|
|
|
| +void ThisFunction::CollectInfo(AstNodeType::Flag* flags,
|
| + int* node_count) const {
|
| + *flags |= AstNodeType::kThisFunctionMask;
|
| + *node_count += 1;
|
| +}
|
| +
|
| +
|
| bool SharedFunctionInfoLiteral::IsInlineable() const {
|
| return false;
|
| }
|
|
|
|
|
| +void SharedFunctionInfoLiteral::CollectInfo(AstNodeType::Flag* flags,
|
| + int* node_count) const {
|
| + *flags |= AstNodeType::kSharedFunctionInfoLiteralMask;
|
| + *node_count += 1;
|
| +}
|
| +
|
| +
|
| bool ForStatement::IsInlineable() const {
|
| return (init() == NULL || init()->IsInlineable())
|
| && (cond() == NULL || cond()->IsInlineable())
|
| @@ -502,33 +644,82 @@ bool ForStatement::IsInlineable() const {
|
| }
|
|
|
|
|
| +void ForStatement::CollectInfo(AstNodeType::Flag* flags,
|
| + int* node_count) const {
|
| + *flags |= AstNodeType::kForStatementMask;
|
| + if (init() != NULL) init()->CollectInfo(flags, node_count);
|
| + if (cond() != NULL) cond()->CollectInfo(flags, node_count);
|
| + if (next() != NULL) next()->CollectInfo(flags, node_count);
|
| + body()->CollectInfo(flags, node_count);
|
| + *node_count += 1;
|
| +}
|
| +
|
| +
|
| bool WhileStatement::IsInlineable() const {
|
| return cond()->IsInlineable()
|
| && body()->IsInlineable();
|
| }
|
|
|
|
|
| +void WhileStatement::CollectInfo(AstNodeType::Flag* flags,
|
| + int* node_count) const {
|
| + *flags |= AstNodeType::kWhileStatementMask;
|
| + cond()->CollectInfo(flags, node_count);
|
| + body()->CollectInfo(flags, node_count);
|
| + *node_count += 1;
|
| +}
|
| +
|
| +
|
| bool DoWhileStatement::IsInlineable() const {
|
| return cond()->IsInlineable()
|
| && body()->IsInlineable();
|
| }
|
|
|
|
|
| +void DoWhileStatement::CollectInfo(AstNodeType::Flag* flags,
|
| + int* node_count) const {
|
| + *flags |= AstNodeType::kDoWhileStatementMask;
|
| + cond()->CollectInfo(flags, node_count);
|
| + body()->CollectInfo(flags, node_count);
|
| + *node_count += 1;
|
| +}
|
| +
|
| +
|
| bool ContinueStatement::IsInlineable() const {
|
| return true;
|
| }
|
|
|
|
|
| +void ContinueStatement::CollectInfo(AstNodeType::Flag* flags,
|
| + int* node_count) const {
|
| + *flags |= AstNodeType::kContinueStatementMask;
|
| + *node_count += 1;
|
| +}
|
| +
|
| +
|
| bool BreakStatement::IsInlineable() const {
|
| return true;
|
| }
|
|
|
|
|
| +void BreakStatement::CollectInfo(AstNodeType::Flag* flags,
|
| + int* node_count) const {
|
| + *flags |= AstNodeType::kBreakStatementMask;
|
| + *node_count += 1;
|
| +}
|
| +
|
| +
|
| bool EmptyStatement::IsInlineable() const {
|
| return true;
|
| }
|
|
|
|
|
| +void EmptyStatement::CollectInfo(AstNodeType::Flag* flags,
|
| + int* node_count) const {
|
| + // Nothing to see here, move on.
|
| +}
|
| +
|
| +
|
| bool Literal::IsInlineable() const {
|
| return true;
|
| }
|
| @@ -543,11 +734,25 @@ bool Block::IsInlineable() const {
|
| }
|
|
|
|
|
| +void Block::CollectInfo(AstNodeType::Flag* flags, int* node_count) const {
|
| + for (int i = 0; i < statements_.length(); ++i) {
|
| + statements_[i]->CollectInfo(flags, node_count);
|
| + }
|
| + *node_count += 1;
|
| +}
|
| +
|
| +
|
| bool ExpressionStatement::IsInlineable() const {
|
| return expression()->IsInlineable();
|
| }
|
|
|
|
|
| +void ExpressionStatement::CollectInfo(AstNodeType::Flag* flags,
|
| + int* node_count) const {
|
| + expression()->CollectInfo(flags, node_count);
|
| +}
|
| +
|
| +
|
| bool IfStatement::IsInlineable() const {
|
| return condition()->IsInlineable()
|
| && then_statement()->IsInlineable()
|
| @@ -555,17 +760,46 @@ bool IfStatement::IsInlineable() const {
|
| }
|
|
|
|
|
| +void IfStatement::CollectInfo(AstNodeType::Flag* flags,
|
| + int* node_count) const {
|
| + *flags |= AstNodeType::kIfStatementMask;
|
| + condition()->CollectInfo(flags, node_count);
|
| + then_statement()->CollectInfo(flags, node_count);
|
| + else_statement()->CollectInfo(flags, node_count);
|
| + *node_count += 1;
|
| +}
|
| +
|
| +
|
| +
|
| bool ReturnStatement::IsInlineable() const {
|
| return expression()->IsInlineable();
|
| }
|
|
|
|
|
| +void ReturnStatement::CollectInfo(AstNodeType::Flag* flags,
|
| + int* node_count) const {
|
| + *flags |= AstNodeType::kReturnStatementMask;
|
| + expression()->CollectInfo(flags, node_count);
|
| + *node_count += 1;
|
| +}
|
| +
|
| +
|
| bool Conditional::IsInlineable() const {
|
| return condition()->IsInlineable() && then_expression()->IsInlineable() &&
|
| else_expression()->IsInlineable();
|
| }
|
|
|
|
|
| +void Conditional::CollectInfo(AstNodeType::Flag* flags,
|
| + int* node_count) const {
|
| + *flags |= AstNodeType::kConditionalMask;
|
| + condition()->CollectInfo(flags, node_count);
|
| + then_expression()->CollectInfo(flags, node_count);
|
| + else_expression()->CollectInfo(flags, node_count);
|
| + *node_count += 1;
|
| +}
|
| +
|
| +
|
| bool VariableProxy::IsInlineable() const {
|
| return var()->IsUnallocated()
|
| || var()->IsStackAllocated()
|
| @@ -578,11 +812,28 @@ bool Assignment::IsInlineable() const {
|
| }
|
|
|
|
|
| +void Assignment::CollectInfo(AstNodeType::Flag* flags,
|
| + int* node_count) const {
|
| + target()->CollectInfo(flags, node_count);
|
| + value()->CollectInfo(flags, node_count);
|
| + *node_count += 1;
|
| +}
|
| +
|
| +
|
| bool Property::IsInlineable() const {
|
| return obj()->IsInlineable() && key()->IsInlineable();
|
| }
|
|
|
|
|
| +void Property::CollectInfo(AstNodeType::Flag* flags,
|
| + int* node_count) const {
|
| + *flags |= AstNodeType::kPropertyMask;
|
| + obj()->CollectInfo(flags, node_count);
|
| + key()->CollectInfo(flags, node_count);
|
| + *node_count += 1;
|
| +}
|
| +
|
| +
|
| bool Call::IsInlineable() const {
|
| if (!expression()->IsInlineable()) return false;
|
| const int count = arguments()->length();
|
| @@ -593,6 +844,16 @@ bool Call::IsInlineable() const {
|
| }
|
|
|
|
|
| +void Call::CollectInfo(AstNodeType::Flag* flags, int* node_count) const {
|
| + *flags |= AstNodeType::kCallMask;
|
| + expression()->CollectInfo(flags, node_count);
|
| + for (int i = 0; i < arguments()->length(); ++i) {
|
| + arguments()->at(i)->CollectInfo(flags, node_count);
|
| + }
|
| + *node_count += 1;
|
| +}
|
| +
|
| +
|
| bool CallNew::IsInlineable() const {
|
| if (!expression()->IsInlineable()) return false;
|
| const int count = arguments()->length();
|
| @@ -603,6 +864,16 @@ bool CallNew::IsInlineable() const {
|
| }
|
|
|
|
|
| +void CallNew::CollectInfo(AstNodeType::Flag* flags, int* node_count) const {
|
| + *flags |= AstNodeType::kCallNewMask;
|
| + expression()->CollectInfo(flags, node_count);
|
| + for (int i = 0; i < arguments()->length(); ++i) {
|
| + arguments()->at(i)->CollectInfo(flags, node_count);
|
| + }
|
| + *node_count += 1;
|
| +}
|
| +
|
| +
|
| bool CallRuntime::IsInlineable() const {
|
| // Don't try to inline JS runtime calls because we don't (currently) even
|
| // optimize them.
|
| @@ -623,26 +894,65 @@ bool CallRuntime::IsInlineable() const {
|
| }
|
|
|
|
|
| +void CallRuntime::CollectInfo(AstNodeType::Flag* flags, int* node_count) const {
|
| + *flags |= AstNodeType::kCallRuntimeMask;
|
| + for (int i = 0; i < arguments()->length(); ++i) {
|
| + arguments()->at(i)->CollectInfo(flags, node_count);
|
| + }
|
| + *node_count += 1;
|
| +}
|
| +
|
| +
|
| bool UnaryOperation::IsInlineable() const {
|
| return expression()->IsInlineable();
|
| }
|
|
|
|
|
| +void UnaryOperation::CollectInfo(AstNodeType::Flag* flags,
|
| + int* node_count) const {
|
| + expression()->CollectInfo(flags, node_count);
|
| + *node_count += 1;
|
| +}
|
| +
|
| +
|
| bool BinaryOperation::IsInlineable() const {
|
| return left()->IsInlineable() && right()->IsInlineable();
|
| }
|
|
|
|
|
| +void BinaryOperation::CollectInfo(AstNodeType::Flag* flags,
|
| + int* node_count) const {
|
| + left()->CollectInfo(flags, node_count);
|
| + right()->CollectInfo(flags, node_count);
|
| + *node_count += 1;
|
| +}
|
| +
|
| +
|
| bool CompareOperation::IsInlineable() const {
|
| return left()->IsInlineable() && right()->IsInlineable();
|
| }
|
|
|
|
|
| +void CompareOperation::CollectInfo(AstNodeType::Flag* flags,
|
| + int* node_count) const {
|
| + left()->CollectInfo(flags, node_count);
|
| + right()->CollectInfo(flags, node_count);
|
| + *node_count += 1;
|
| +}
|
| +
|
| +
|
| bool CountOperation::IsInlineable() const {
|
| return expression()->IsInlineable();
|
| }
|
|
|
|
|
| +void CountOperation::CollectInfo(AstNodeType::Flag* flags,
|
| + int* node_count) const {
|
| + expression()->CollectInfo(flags, node_count);
|
| + *node_count += 1;
|
| +}
|
| +
|
| +
|
| // ----------------------------------------------------------------------------
|
| // Recording of type feedback
|
|
|
|
|