Pull from svn bleeding_edge@3716
diff --git a/src/compiler.cc b/src/compiler.cc
index b7aaedf..fe61571 100644
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -32,7 +32,7 @@
 #include "compilation-cache.h"
 #include "compiler.h"
 #include "debug.h"
-#include "fast-codegen.h"
+#include "full-codegen.h"
 #include "oprofile-agent.h"
 #include "rewriter.h"
 #include "scopes.h"
@@ -42,29 +42,6 @@
 namespace internal {
 
 
-class CodeGenSelector: public AstVisitor {
- public:
-  enum CodeGenTag { NORMAL, FAST };
-
-  CodeGenSelector() : has_supported_syntax_(true) {}
-
-  CodeGenTag Select(FunctionLiteral* fun);
-
- private:
-  void VisitDeclarations(ZoneList<Declaration*>* decls);
-  void VisitStatements(ZoneList<Statement*>* stmts);
-
-  // AST node visit functions.
-#define DECLARE_VISIT(type) virtual void Visit##type(type* node);
-  AST_NODE_LIST(DECLARE_VISIT)
-#undef DECLARE_VISIT
-
-  bool has_supported_syntax_;
-
-  DISALLOW_COPY_AND_ASSIGN(CodeGenSelector);
-};
-
-
 static Handle<Code> MakeCode(FunctionLiteral* literal,
                              Handle<Script> script,
                              Handle<Context> context,
@@ -117,12 +94,11 @@
                !FLAG_always_fast_compiler) {
       if (FLAG_trace_bailout) PrintF("No hint to try fast\n");
     } else {
-      CodeGenSelector selector;
-      CodeGenSelector::CodeGenTag code_gen = selector.Select(literal);
-      if (code_gen == CodeGenSelector::FAST) {
-        return FastCodeGenerator::MakeCode(literal, script, is_eval);
+      FullCodeGenSyntaxChecker checker;
+      checker.Check(literal);
+      if (checker.has_supported_syntax()) {
+        return FullCodeGenerator::MakeCode(literal, script, is_eval);
       }
-      ASSERT(code_gen == CodeGenSelector::NORMAL);
     }
   }
   return CodeGenerator::MakeCode(literal, script, is_eval);
@@ -493,11 +469,12 @@
 
     // Generate code and return it.
     bool is_compiled = false;
-    if (FLAG_fast_compiler && literal->try_fast_codegen()) {
-      CodeGenSelector selector;
-      CodeGenSelector::CodeGenTag code_gen = selector.Select(literal);
-      if (code_gen == CodeGenSelector::FAST) {
-        code = FastCodeGenerator::MakeCode(literal,
+    if (FLAG_always_fast_compiler ||
+        (FLAG_fast_compiler && literal->try_fast_codegen())) {
+      FullCodeGenSyntaxChecker checker;
+      checker.Check(literal);
+      if (checker.has_supported_syntax()) {
+        code = FullCodeGenerator::MakeCode(literal,
                                            script,
                                            false);  // Not eval.
         is_compiled = true;
@@ -571,418 +548,4 @@
 }
 
 
-CodeGenSelector::CodeGenTag CodeGenSelector::Select(FunctionLiteral* fun) {
-  Scope* scope = fun->scope();
-
-  if (scope->num_heap_slots() > 0) {
-    // We support functions with a local context if they do not have
-    // parameters that need to be copied into the context.
-    for (int i = 0, len = scope->num_parameters(); i < len; i++) {
-      Slot* slot = scope->parameter(i)->slot();
-      if (slot != NULL && slot->type() == Slot::CONTEXT) {
-        if (FLAG_trace_bailout) {
-          PrintF("Function has context-allocated parameters.\n");
-        }
-        return NORMAL;
-      }
-    }
-  }
-
-  has_supported_syntax_ = true;
-  VisitDeclarations(scope->declarations());
-  if (!has_supported_syntax_) return NORMAL;
-
-  VisitStatements(fun->body());
-  return has_supported_syntax_ ? FAST : NORMAL;
-}
-
-
-#define BAILOUT(reason)                         \
-  do {                                          \
-    if (FLAG_trace_bailout) {                   \
-      PrintF("%s\n", reason);                   \
-    }                                           \
-    has_supported_syntax_ = false;              \
-    return;                                     \
-  } while (false)
-
-
-#define CHECK_BAILOUT                           \
-  do {                                          \
-    if (!has_supported_syntax_) return;         \
-  } while (false)
-
-
-void CodeGenSelector::VisitDeclarations(ZoneList<Declaration*>* decls) {
-  for (int i = 0; i < decls->length(); i++) {
-    Visit(decls->at(i));
-    CHECK_BAILOUT;
-  }
-}
-
-
-void CodeGenSelector::VisitStatements(ZoneList<Statement*>* stmts) {
-  for (int i = 0, len = stmts->length(); i < len; i++) {
-    Visit(stmts->at(i));
-    CHECK_BAILOUT;
-  }
-}
-
-
-void CodeGenSelector::VisitDeclaration(Declaration* decl) {
-  Property* prop = decl->proxy()->AsProperty();
-  if (prop != NULL) {
-    Visit(prop->obj());
-    Visit(prop->key());
-  }
-
-  if (decl->fun() != NULL) {
-    Visit(decl->fun());
-  }
-}
-
-
-void CodeGenSelector::VisitBlock(Block* stmt) {
-  VisitStatements(stmt->statements());
-}
-
-
-void CodeGenSelector::VisitExpressionStatement(ExpressionStatement* stmt) {
-  Visit(stmt->expression());
-}
-
-
-void CodeGenSelector::VisitEmptyStatement(EmptyStatement* stmt) {}
-
-
-void CodeGenSelector::VisitIfStatement(IfStatement* stmt) {
-  Visit(stmt->condition());
-  CHECK_BAILOUT;
-  Visit(stmt->then_statement());
-  CHECK_BAILOUT;
-  Visit(stmt->else_statement());
-}
-
-
-void CodeGenSelector::VisitContinueStatement(ContinueStatement* stmt) {}
-
-
-void CodeGenSelector::VisitBreakStatement(BreakStatement* stmt) {}
-
-
-void CodeGenSelector::VisitReturnStatement(ReturnStatement* stmt) {
-  Visit(stmt->expression());
-}
-
-
-void CodeGenSelector::VisitWithEnterStatement(WithEnterStatement* stmt) {
-  Visit(stmt->expression());
-}
-
-
-void CodeGenSelector::VisitWithExitStatement(WithExitStatement* stmt) {}
-
-
-void CodeGenSelector::VisitSwitchStatement(SwitchStatement* stmt) {
-  BAILOUT("SwitchStatement");
-}
-
-
-void CodeGenSelector::VisitDoWhileStatement(DoWhileStatement* stmt) {
-  Visit(stmt->cond());
-  CHECK_BAILOUT;
-  Visit(stmt->body());
-}
-
-
-void CodeGenSelector::VisitWhileStatement(WhileStatement* stmt) {
-  Visit(stmt->cond());
-  CHECK_BAILOUT;
-  Visit(stmt->body());
-}
-
-
-void CodeGenSelector::VisitForStatement(ForStatement* stmt) {
-  BAILOUT("ForStatement");
-}
-
-
-void CodeGenSelector::VisitForInStatement(ForInStatement* stmt) {
-  BAILOUT("ForInStatement");
-}
-
-
-void CodeGenSelector::VisitTryCatchStatement(TryCatchStatement* stmt) {
-  Visit(stmt->try_block());
-  CHECK_BAILOUT;
-  Visit(stmt->catch_block());
-}
-
-
-void CodeGenSelector::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
-  Visit(stmt->try_block());
-  CHECK_BAILOUT;
-  Visit(stmt->finally_block());
-}
-
-
-void CodeGenSelector::VisitDebuggerStatement(DebuggerStatement* stmt) {}
-
-
-void CodeGenSelector::VisitFunctionLiteral(FunctionLiteral* expr) {}
-
-
-void CodeGenSelector::VisitFunctionBoilerplateLiteral(
-    FunctionBoilerplateLiteral* expr) {
-  BAILOUT("FunctionBoilerplateLiteral");
-}
-
-
-void CodeGenSelector::VisitConditional(Conditional* expr) {
-  Visit(expr->condition());
-  CHECK_BAILOUT;
-  Visit(expr->then_expression());
-  CHECK_BAILOUT;
-  Visit(expr->else_expression());
-}
-
-
-void CodeGenSelector::VisitSlot(Slot* expr) {
-  UNREACHABLE();
-}
-
-
-void CodeGenSelector::VisitVariableProxy(VariableProxy* expr) {
-  Variable* var = expr->var();
-  if (!var->is_global()) {
-    Slot* slot = var->slot();
-    if (slot != NULL) {
-      Slot::Type type = slot->type();
-      // When LOOKUP slots are enabled, some currently dead code
-      // implementing unary typeof will become live.
-      if (type == Slot::LOOKUP) {
-        BAILOUT("Lookup slot");
-      }
-    } else {
-      // If not global or a slot, it is a parameter rewritten to an explicit
-      // property reference on the (shadow) arguments object.
-#ifdef DEBUG
-      Property* property = var->AsProperty();
-      ASSERT_NOT_NULL(property);
-      Variable* object = property->obj()->AsVariableProxy()->AsVariable();
-      ASSERT_NOT_NULL(object);
-      ASSERT_NOT_NULL(object->slot());
-      ASSERT_NOT_NULL(property->key()->AsLiteral());
-      ASSERT(property->key()->AsLiteral()->handle()->IsSmi());
-#endif
-    }
-  }
-}
-
-
-void CodeGenSelector::VisitLiteral(Literal* expr) {}
-
-
-void CodeGenSelector::VisitRegExpLiteral(RegExpLiteral* expr) {}
-
-
-void CodeGenSelector::VisitObjectLiteral(ObjectLiteral* expr) {
-  ZoneList<ObjectLiteral::Property*>* properties = expr->properties();
-
-  for (int i = 0, len = properties->length(); i < len; i++) {
-    ObjectLiteral::Property* property = properties->at(i);
-    if (property->IsCompileTimeValue()) continue;
-    Visit(property->key());
-    CHECK_BAILOUT;
-    Visit(property->value());
-    CHECK_BAILOUT;
-  }
-}
-
-
-void CodeGenSelector::VisitArrayLiteral(ArrayLiteral* expr) {
-  ZoneList<Expression*>* subexprs = expr->values();
-  for (int i = 0, len = subexprs->length(); i < len; i++) {
-    Expression* subexpr = subexprs->at(i);
-    if (subexpr->AsLiteral() != NULL) continue;
-    if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue;
-    Visit(subexpr);
-    CHECK_BAILOUT;
-  }
-}
-
-
-void CodeGenSelector::VisitCatchExtensionObject(CatchExtensionObject* expr) {
-  Visit(expr->key());
-  CHECK_BAILOUT;
-  Visit(expr->value());
-}
-
-
-void CodeGenSelector::VisitAssignment(Assignment* expr) {
-  // We support plain non-compound assignments to properties, parameters and
-  // non-context (stack-allocated) locals, and global variables.
-  Token::Value op = expr->op();
-  if (op == Token::INIT_CONST) BAILOUT("initialize constant");
-
-  Variable* var = expr->target()->AsVariableProxy()->AsVariable();
-  Property* prop = expr->target()->AsProperty();
-  ASSERT(var == NULL || prop == NULL);
-  if (var != NULL) {
-    if (var->mode() == Variable::CONST) {
-      BAILOUT("Assignment to const");
-    }
-    // All global variables are supported.
-    if (!var->is_global()) {
-      ASSERT(var->slot() != NULL);
-      Slot::Type type = var->slot()->type();
-      if (type == Slot::LOOKUP) {
-        BAILOUT("Lookup slot");
-      }
-    }
-  } else if (prop != NULL) {
-    Visit(prop->obj());
-    CHECK_BAILOUT;
-    Visit(prop->key());
-    CHECK_BAILOUT;
-  } else {
-    // This is a throw reference error.
-    BAILOUT("non-variable/non-property assignment");
-  }
-
-  Visit(expr->value());
-}
-
-
-void CodeGenSelector::VisitThrow(Throw* expr) {
-  Visit(expr->exception());
-}
-
-
-void CodeGenSelector::VisitProperty(Property* expr) {
-  Visit(expr->obj());
-  CHECK_BAILOUT;
-  Visit(expr->key());
-}
-
-
-void CodeGenSelector::VisitCall(Call* expr) {
-  Expression* fun = expr->expression();
-  ZoneList<Expression*>* args = expr->arguments();
-  Variable* var = fun->AsVariableProxy()->AsVariable();
-
-  // Check for supported calls
-  if (var != NULL && var->is_possibly_eval()) {
-    BAILOUT("call to the identifier 'eval'");
-  } else if (var != NULL && !var->is_this() && var->is_global()) {
-    // Calls to global variables are supported.
-  } else if (var != NULL && var->slot() != NULL &&
-             var->slot()->type() == Slot::LOOKUP) {
-    BAILOUT("call to a lookup slot");
-  } else if (fun->AsProperty() != NULL) {
-    Property* prop = fun->AsProperty();
-    Visit(prop->obj());
-    CHECK_BAILOUT;
-    Visit(prop->key());
-    CHECK_BAILOUT;
-  } else {
-    // Otherwise the call is supported if the function expression is.
-    Visit(fun);
-  }
-  // Check all arguments to the call.
-  for (int i = 0; i < args->length(); i++) {
-    Visit(args->at(i));
-    CHECK_BAILOUT;
-  }
-}
-
-
-void CodeGenSelector::VisitCallNew(CallNew* expr) {
-  Visit(expr->expression());
-  CHECK_BAILOUT;
-  ZoneList<Expression*>* args = expr->arguments();
-  // Check all arguments to the call
-  for (int i = 0; i < args->length(); i++) {
-    Visit(args->at(i));
-    CHECK_BAILOUT;
-  }
-}
-
-
-void CodeGenSelector::VisitCallRuntime(CallRuntime* expr) {
-  // Check for inline runtime call
-  if (expr->name()->Get(0) == '_' &&
-      CodeGenerator::FindInlineRuntimeLUT(expr->name()) != NULL) {
-    BAILOUT("inlined runtime call");
-  }
-  // Check all arguments to the call.  (Relies on TEMP meaning STACK.)
-  for (int i = 0; i < expr->arguments()->length(); i++) {
-    Visit(expr->arguments()->at(i));
-    CHECK_BAILOUT;
-  }
-}
-
-
-void CodeGenSelector::VisitUnaryOperation(UnaryOperation* expr) {
-  switch (expr->op()) {
-    case Token::VOID:
-    case Token::NOT:
-    case Token::TYPEOF:
-      Visit(expr->expression());
-      break;
-    case Token::BIT_NOT:
-      BAILOUT("UnaryOperataion: BIT_NOT");
-    case Token::DELETE:
-      BAILOUT("UnaryOperataion: DELETE");
-    default:
-      BAILOUT("UnaryOperataion");
-  }
-}
-
-
-void CodeGenSelector::VisitCountOperation(CountOperation* expr) {
-  Variable* var = expr->expression()->AsVariableProxy()->AsVariable();
-  Property* prop = expr->expression()->AsProperty();
-  ASSERT(var == NULL || prop == NULL);
-  if (var != NULL) {
-    // All global variables are supported.
-    if (!var->is_global()) {
-      ASSERT(var->slot() != NULL);
-      Slot::Type type = var->slot()->type();
-      if (type == Slot::LOOKUP) {
-        BAILOUT("CountOperation with lookup slot");
-      }
-    }
-  } else if (prop != NULL) {
-    Visit(prop->obj());
-    CHECK_BAILOUT;
-    Visit(prop->key());
-    CHECK_BAILOUT;
-  } else {
-    // This is a throw reference error.
-    BAILOUT("CountOperation non-variable/non-property expression");
-  }
-}
-
-
-void CodeGenSelector::VisitBinaryOperation(BinaryOperation* expr) {
-  Visit(expr->left());
-  CHECK_BAILOUT;
-  Visit(expr->right());
-}
-
-
-void CodeGenSelector::VisitCompareOperation(CompareOperation* expr) {
-  Visit(expr->left());
-  CHECK_BAILOUT;
-  Visit(expr->right());
-}
-
-
-void CodeGenSelector::VisitThisFunction(ThisFunction* expr) {}
-
-#undef BAILOUT
-#undef CHECK_BAILOUT
-
-
 } }  // namespace v8::internal