// Copyright 2014 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/compiler/ast-graph-builder.h"

#include "src/compiler.h"
#include "src/compiler/control-builders.h"
#include "src/compiler/node-properties.h"
#include "src/compiler/node-properties-inl.h"
#include "src/full-codegen.h"
#include "src/parser.h"
#include "src/scopes.h"

namespace v8 {
namespace internal {
namespace compiler {

AstGraphBuilder::AstGraphBuilder(CompilationInfo* info, JSGraph* jsgraph)
    : StructuredGraphBuilder(jsgraph->graph(), jsgraph->common()),
      info_(info),
      jsgraph_(jsgraph),
      globals_(0, info->zone()),
      breakable_(NULL),
      execution_context_(NULL) {
  InitializeAstVisitor(info->zone());
}


Node* AstGraphBuilder::GetFunctionClosure() {
  if (!function_closure_.is_set()) {
    // Parameter -1 is special for the function closure
    Operator* op = common()->Parameter(-1);
    Node* node = NewNode(op, graph()->start());
    function_closure_.set(node);
  }
  return function_closure_.get();
}


Node* AstGraphBuilder::GetFunctionContext() {
  if (!function_context_.is_set()) {
    // Parameter (arity + 1) is special for the outer context of the function
    Operator* op = common()->Parameter(info()->num_parameters() + 1);
    Node* node = NewNode(op, graph()->start());
    function_context_.set(node);
  }
  return function_context_.get();
}


bool AstGraphBuilder::CreateGraph() {
  Scope* scope = info()->scope();
  DCHECK(graph() != NULL);

  // Set up the basic structure of the graph.
  int parameter_count = info()->num_parameters();
  graph()->SetStart(graph()->NewNode(common()->Start(parameter_count)));

  // Initialize the top-level environment.
  Environment env(this, scope, graph()->start());
  set_environment(&env);

  // Build node to initialize local function context.
  Node* closure = GetFunctionClosure();
  Node* outer = GetFunctionContext();
  Node* inner = BuildLocalFunctionContext(outer, closure);

  // Push top-level function scope for the function body.
  ContextScope top_context(this, scope, inner);

  // Build the arguments object if it is used.
  BuildArgumentsObject(scope->arguments());

  // Emit tracing call if requested to do so.
  if (FLAG_trace) {
    NewNode(javascript()->Runtime(Runtime::kTraceEnter, 0));
  }

  // Visit implicit declaration of the function name.
  if (scope->is_function_scope() && scope->function() != NULL) {
    VisitVariableDeclaration(scope->function());
  }

  // Visit declarations within the function scope.
  VisitDeclarations(scope->declarations());

  // TODO(mstarzinger): This should do an inlined stack check.
  NewNode(javascript()->Runtime(Runtime::kStackGuard, 0));

  // Visit statements in the function body.
  VisitStatements(info()->function()->body());
  if (HasStackOverflow()) return false;

  // Emit tracing call if requested to do so.
  if (FLAG_trace) {
    // TODO(mstarzinger): Only traces implicit return.
    Node* return_value = jsgraph()->UndefinedConstant();
    NewNode(javascript()->Runtime(Runtime::kTraceExit, 1), return_value);
  }

  // Return 'undefined' in case we can fall off the end.
  Node* control = NewNode(common()->Return(), jsgraph()->UndefinedConstant());
  UpdateControlDependencyToLeaveFunction(control);

  // Finish the basic structure of the graph.
  environment()->UpdateControlDependency(exit_control());
  graph()->SetEnd(NewNode(common()->End()));

  return true;
}


// Left-hand side can only be a property, a global or a variable slot.
enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };


// Determine the left-hand side kind of an assignment.
static LhsKind DetermineLhsKind(Expression* expr) {
  Property* property = expr->AsProperty();
  DCHECK(expr->IsValidReferenceExpression());
  LhsKind lhs_kind =
      (property == NULL) ? VARIABLE : (property->key()->IsPropertyName())
                                          ? NAMED_PROPERTY
                                          : KEYED_PROPERTY;
  return lhs_kind;
}


// Helper to find an existing shared function info in the baseline code for the
// given function literal. Used to canonicalize SharedFunctionInfo objects.
static Handle<SharedFunctionInfo> SearchSharedFunctionInfo(
    Code* unoptimized_code, FunctionLiteral* expr) {
  int start_position = expr->start_position();
  for (RelocIterator it(unoptimized_code); !it.done(); it.next()) {
    RelocInfo* rinfo = it.rinfo();
    if (rinfo->rmode() != RelocInfo::EMBEDDED_OBJECT) continue;
    Object* obj = rinfo->target_object();
    if (obj->IsSharedFunctionInfo()) {
      SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj);
      if (shared->start_position() == start_position) {
        return Handle<SharedFunctionInfo>(shared);
      }
    }
  }
  return Handle<SharedFunctionInfo>();
}


StructuredGraphBuilder::Environment* AstGraphBuilder::CopyEnvironment(
    StructuredGraphBuilder::Environment* env) {
  return new (zone()) Environment(*reinterpret_cast<Environment*>(env));
}


AstGraphBuilder::Environment::Environment(AstGraphBuilder* builder,
                                          Scope* scope,
                                          Node* control_dependency)
    : StructuredGraphBuilder::Environment(builder, control_dependency),
      parameters_count_(scope->num_parameters() + 1),
      locals_count_(scope->num_stack_slots()),
      parameters_node_(NULL),
      locals_node_(NULL),
      stack_node_(NULL),
      parameters_dirty_(true),
      locals_dirty_(true),
      stack_dirty_(true) {
  DCHECK_EQ(scope->num_parameters() + 1, parameters_count());

  // Bind the receiver variable.
  Node* receiver = builder->graph()->NewNode(common()->Parameter(0),
                                             builder->graph()->start());
  values()->push_back(receiver);

  // Bind all parameter variables. The parameter indices are shifted by 1
  // (receiver is parameter index -1 but environment index 0).
  for (int i = 0; i < scope->num_parameters(); ++i) {
    Node* parameter = builder->graph()->NewNode(common()->Parameter(i + 1),
                                                builder->graph()->start());
    values()->push_back(parameter);
  }

  // Bind all local variables to undefined.
  Node* undefined_constant = builder->jsgraph()->UndefinedConstant();
  values()->insert(values()->end(), locals_count(), undefined_constant);
}


AstGraphBuilder::Environment::Environment(const Environment& copy)
    : StructuredGraphBuilder::Environment(
          static_cast<StructuredGraphBuilder::Environment>(copy)),
      parameters_count_(copy.parameters_count_),
      locals_count_(copy.locals_count_),
      parameters_node_(copy.parameters_node_),
      locals_node_(copy.locals_node_),
      stack_node_(copy.stack_node_),
      parameters_dirty_(copy.parameters_dirty_),
      locals_dirty_(copy.locals_dirty_),
      stack_dirty_(copy.stack_dirty_) {}


Node* AstGraphBuilder::Environment::Checkpoint(BailoutId ast_id) {
  if (parameters_dirty_) {
    Operator* op = common()->StateValues(parameters_count());
    if (parameters_count() != 0) {
      Node** parameters = &values()->front();
      parameters_node_ = graph()->NewNode(op, parameters_count(), parameters);
    } else {
      parameters_node_ = graph()->NewNode(op);
    }
    parameters_dirty_ = false;
  }
  if (locals_dirty_) {
    Operator* op = common()->StateValues(locals_count());
    if (locals_count() != 0) {
      Node** locals = &values()->at(parameters_count_);
      locals_node_ = graph()->NewNode(op, locals_count(), locals);
    } else {
      locals_node_ = graph()->NewNode(op);
    }
    locals_dirty_ = false;
  }
  if (stack_dirty_) {
    Operator* op = common()->StateValues(stack_height());
    if (stack_height() != 0) {
      Node** stack = &values()->at(parameters_count_ + locals_count_);
      stack_node_ = graph()->NewNode(op, stack_height(), stack);
    } else {
      stack_node_ = graph()->NewNode(op);
    }
    stack_dirty_ = false;
  }

  Operator* op = common()->FrameState(ast_id);

  return graph()->NewNode(op, parameters_node_, locals_node_, stack_node_);
}


AstGraphBuilder::AstContext::AstContext(AstGraphBuilder* own,
                                        Expression::Context kind,
                                        BailoutId bailout_id)
    : bailout_id_(bailout_id),
      kind_(kind),
      owner_(own),
      outer_(own->ast_context()) {
  owner()->set_ast_context(this);  // Push.
#ifdef DEBUG
  original_height_ = environment()->stack_height();
#endif
}


AstGraphBuilder::AstContext::~AstContext() {
  owner()->set_ast_context(outer_);  // Pop.
}


AstGraphBuilder::AstEffectContext::~AstEffectContext() {
  DCHECK(environment()->stack_height() == original_height_);
}


AstGraphBuilder::AstValueContext::~AstValueContext() {
  DCHECK(environment()->stack_height() == original_height_ + 1);
}


AstGraphBuilder::AstTestContext::~AstTestContext() {
  DCHECK(environment()->stack_height() == original_height_ + 1);
}


void AstGraphBuilder::AstEffectContext::ProduceValueWithLazyBailout(
    Node* value) {
  ProduceValue(value);
  owner()->BuildLazyBailout(value, bailout_id_);
}


void AstGraphBuilder::AstValueContext::ProduceValueWithLazyBailout(
    Node* value) {
  ProduceValue(value);
  owner()->BuildLazyBailout(value, bailout_id_);
}


void AstGraphBuilder::AstTestContext::ProduceValueWithLazyBailout(Node* value) {
  environment()->Push(value);
  owner()->BuildLazyBailout(value, bailout_id_);
  environment()->Pop();
  ProduceValue(value);
}


void AstGraphBuilder::AstEffectContext::ProduceValue(Node* value) {
  // The value is ignored.
}


void AstGraphBuilder::AstValueContext::ProduceValue(Node* value) {
  environment()->Push(value);
}


void AstGraphBuilder::AstTestContext::ProduceValue(Node* value) {
  environment()->Push(owner()->BuildToBoolean(value));
}


Node* AstGraphBuilder::AstEffectContext::ConsumeValue() { return NULL; }


Node* AstGraphBuilder::AstValueContext::ConsumeValue() {
  return environment()->Pop();
}


Node* AstGraphBuilder::AstTestContext::ConsumeValue() {
  return environment()->Pop();
}


AstGraphBuilder::BreakableScope* AstGraphBuilder::BreakableScope::FindBreakable(
    BreakableStatement* target) {
  BreakableScope* current = this;
  while (current != NULL && current->target_ != target) {
    owner_->environment()->Drop(current->drop_extra_);
    current = current->next_;
  }
  DCHECK(current != NULL);  // Always found (unless stack is malformed).
  return current;
}


void AstGraphBuilder::BreakableScope::BreakTarget(BreakableStatement* stmt) {
  FindBreakable(stmt)->control_->Break();
}


void AstGraphBuilder::BreakableScope::ContinueTarget(BreakableStatement* stmt) {
  FindBreakable(stmt)->control_->Continue();
}


void AstGraphBuilder::VisitForValueOrNull(Expression* expr) {
  if (expr == NULL) {
    return environment()->Push(jsgraph()->NullConstant());
  }
  VisitForValue(expr);
}


void AstGraphBuilder::VisitForValues(ZoneList<Expression*>* exprs) {
  for (int i = 0; i < exprs->length(); ++i) {
    VisitForValue(exprs->at(i));
  }
}


void AstGraphBuilder::VisitForValue(Expression* expr) {
  AstValueContext for_value(this, expr->id());
  if (!HasStackOverflow()) {
    expr->Accept(this);
  }
}


void AstGraphBuilder::VisitForEffect(Expression* expr) {
  AstEffectContext for_effect(this, expr->id());
  if (!HasStackOverflow()) {
    expr->Accept(this);
  }
}


void AstGraphBuilder::VisitForTest(Expression* expr) {
  AstTestContext for_condition(this, expr->id());
  if (!HasStackOverflow()) {
    expr->Accept(this);
  }
}


void AstGraphBuilder::VisitVariableDeclaration(VariableDeclaration* decl) {
  Variable* variable = decl->proxy()->var();
  VariableMode mode = decl->mode();
  bool hole_init = mode == CONST || mode == CONST_LEGACY || mode == LET;
  switch (variable->location()) {
    case Variable::UNALLOCATED: {
      Handle<Oddball> value = variable->binding_needs_init()
                                  ? isolate()->factory()->the_hole_value()
                                  : isolate()->factory()->undefined_value();
      globals()->Add(variable->name(), zone());
      globals()->Add(value, zone());
      break;
    }
    case Variable::PARAMETER:
    case Variable::LOCAL:
      if (hole_init) {
        Node* value = jsgraph()->TheHoleConstant();
        environment()->Bind(variable, value);
      }
      break;
    case Variable::CONTEXT:
      if (hole_init) {
        Node* value = jsgraph()->TheHoleConstant();
        Operator* op = javascript()->StoreContext(0, variable->index());
        NewNode(op, current_context(), value);
      }
      break;
    case Variable::LOOKUP:
      UNIMPLEMENTED();
  }
}


void AstGraphBuilder::VisitFunctionDeclaration(FunctionDeclaration* decl) {
  Variable* variable = decl->proxy()->var();
  switch (variable->location()) {
    case Variable::UNALLOCATED: {
      Handle<SharedFunctionInfo> function =
          Compiler::BuildFunctionInfo(decl->fun(), info()->script(), info());
      // Check for stack-overflow exception.
      if (function.is_null()) return SetStackOverflow();
      globals()->Add(variable->name(), zone());
      globals()->Add(function, zone());
      break;
    }
    case Variable::PARAMETER:
    case Variable::LOCAL: {
      VisitForValue(decl->fun());
      Node* value = environment()->Pop();
      environment()->Bind(variable, value);
      break;
    }
    case Variable::CONTEXT: {
      VisitForValue(decl->fun());
      Node* value = environment()->Pop();
      Operator* op = javascript()->StoreContext(0, variable->index());
      NewNode(op, current_context(), value);
      break;
    }
    case Variable::LOOKUP:
      UNIMPLEMENTED();
  }
}


void AstGraphBuilder::VisitModuleDeclaration(ModuleDeclaration* decl) {
  UNREACHABLE();
}


void AstGraphBuilder::VisitImportDeclaration(ImportDeclaration* decl) {
  UNREACHABLE();
}


void AstGraphBuilder::VisitExportDeclaration(ExportDeclaration* decl) {
  UNREACHABLE();
}


void AstGraphBuilder::VisitModuleLiteral(ModuleLiteral* modl) { UNREACHABLE(); }


void AstGraphBuilder::VisitModuleVariable(ModuleVariable* modl) {
  UNREACHABLE();
}


void AstGraphBuilder::VisitModulePath(ModulePath* modl) { UNREACHABLE(); }


void AstGraphBuilder::VisitModuleUrl(ModuleUrl* modl) { UNREACHABLE(); }


void AstGraphBuilder::VisitBlock(Block* stmt) {
  BlockBuilder block(this);
  BreakableScope scope(this, stmt, &block, 0);
  if (stmt->labels() != NULL) block.BeginBlock();
  if (stmt->scope() == NULL) {
    // Visit statements in the same scope, no declarations.
    VisitStatements(stmt->statements());
  } else {
    Operator* op = javascript()->CreateBlockContext();
    Node* scope_info = jsgraph()->Constant(stmt->scope()->GetScopeInfo());
    Node* context = NewNode(op, scope_info, GetFunctionClosure());
    ContextScope scope(this, stmt->scope(), context);

    // Visit declarations and statements in a block scope.
    VisitDeclarations(stmt->scope()->declarations());
    VisitStatements(stmt->statements());
  }
  if (stmt->labels() != NULL) block.EndBlock();
}


void AstGraphBuilder::VisitModuleStatement(ModuleStatement* stmt) {
  UNREACHABLE();
}


void AstGraphBuilder::VisitExpressionStatement(ExpressionStatement* stmt) {
  VisitForEffect(stmt->expression());
}


void AstGraphBuilder::VisitEmptyStatement(EmptyStatement* stmt) {
  // Do nothing.
}


void AstGraphBuilder::VisitIfStatement(IfStatement* stmt) {
  IfBuilder compare_if(this);
  VisitForTest(stmt->condition());
  Node* condition = environment()->Pop();
  compare_if.If(condition);
  compare_if.Then();
  Visit(stmt->then_statement());
  compare_if.Else();
  Visit(stmt->else_statement());
  compare_if.End();
}


void AstGraphBuilder::VisitContinueStatement(ContinueStatement* stmt) {
  StructuredGraphBuilder::Environment* env = environment()->CopyAsUnreachable();
  breakable()->ContinueTarget(stmt->target());
  set_environment(env);
}


void AstGraphBuilder::VisitBreakStatement(BreakStatement* stmt) {
  StructuredGraphBuilder::Environment* env = environment()->CopyAsUnreachable();
  breakable()->BreakTarget(stmt->target());
  set_environment(env);
}


void AstGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) {
  VisitForValue(stmt->expression());
  Node* result = environment()->Pop();
  Node* control = NewNode(common()->Return(), result);
  UpdateControlDependencyToLeaveFunction(control);
}


void AstGraphBuilder::VisitWithStatement(WithStatement* stmt) {
  VisitForValue(stmt->expression());
  Node* value = environment()->Pop();
  Operator* op = javascript()->CreateWithContext();
  Node* context = NewNode(op, value, GetFunctionClosure());
  ContextScope scope(this, stmt->scope(), context);
  Visit(stmt->statement());
}


void AstGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
  ZoneList<CaseClause*>* clauses = stmt->cases();
  SwitchBuilder compare_switch(this, clauses->length());
  BreakableScope scope(this, stmt, &compare_switch, 0);
  compare_switch.BeginSwitch();
  int default_index = -1;

  // Keep the switch value on the stack until a case matches.
  VisitForValue(stmt->tag());
  Node* tag = environment()->Top();

  // Iterate over all cases and create nodes for label comparison.
  for (int i = 0; i < clauses->length(); i++) {
    CaseClause* clause = clauses->at(i);

    // The default is not a test, remember index.
    if (clause->is_default()) {
      default_index = i;
      continue;
    }

    // Create nodes to perform label comparison as if via '==='. The switch
    // value is still on the operand stack while the label is evaluated.
    VisitForValue(clause->label());
    Node* label = environment()->Pop();
    Operator* op = javascript()->StrictEqual();
    Node* condition = NewNode(op, tag, label);
    compare_switch.BeginLabel(i, condition);

    // Discard the switch value at label match.
    environment()->Pop();
    compare_switch.EndLabel();
  }

  // Discard the switch value and mark the default case.
  environment()->Pop();
  if (default_index >= 0) {
    compare_switch.DefaultAt(default_index);
  }

  // Iterate over all cases and create nodes for case bodies.
  for (int i = 0; i < clauses->length(); i++) {
    CaseClause* clause = clauses->at(i);
    compare_switch.BeginCase(i);
    VisitStatements(clause->statements());
    compare_switch.EndCase();
  }

  compare_switch.EndSwitch();
}


void AstGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) {
  LoopBuilder while_loop(this);
  while_loop.BeginLoop();
  VisitIterationBody(stmt, &while_loop, 0);
  while_loop.EndBody();
  VisitForTest(stmt->cond());
  Node* condition = environment()->Pop();
  while_loop.BreakUnless(condition);
  while_loop.EndLoop();
}


void AstGraphBuilder::VisitWhileStatement(WhileStatement* stmt) {
  LoopBuilder while_loop(this);
  while_loop.BeginLoop();
  VisitForTest(stmt->cond());
  Node* condition = environment()->Pop();
  while_loop.BreakUnless(condition);
  VisitIterationBody(stmt, &while_loop, 0);
  while_loop.EndBody();
  while_loop.EndLoop();
}


void AstGraphBuilder::VisitForStatement(ForStatement* stmt) {
  LoopBuilder for_loop(this);
  VisitIfNotNull(stmt->init());
  for_loop.BeginLoop();
  if (stmt->cond() != NULL) {
    VisitForTest(stmt->cond());
    Node* condition = environment()->Pop();
    for_loop.BreakUnless(condition);
  }
  VisitIterationBody(stmt, &for_loop, 0);
  for_loop.EndBody();
  VisitIfNotNull(stmt->next());
  for_loop.EndLoop();
}


// TODO(dcarney): this is a big function.  Try to clean up some.
void AstGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
  VisitForValue(stmt->subject());
  Node* obj = environment()->Pop();
  // Check for undefined or null before entering loop.
  IfBuilder is_undefined(this);
  Node* is_undefined_cond =
      NewNode(javascript()->StrictEqual(), obj, jsgraph()->UndefinedConstant());
  is_undefined.If(is_undefined_cond);
  is_undefined.Then();
  is_undefined.Else();
  {
    IfBuilder is_null(this);
    Node* is_null_cond =
        NewNode(javascript()->StrictEqual(), obj, jsgraph()->NullConstant());
    is_null.If(is_null_cond);
    is_null.Then();
    is_null.Else();
    // Convert object to jsobject.
    // PrepareForBailoutForId(stmt->PrepareId(), TOS_REG);
    obj = NewNode(javascript()->ToObject(), obj);
    environment()->Push(obj);
    // TODO(dcarney): should do a fast enum cache check here to skip runtime.
    environment()->Push(obj);
    Node* cache_type = ProcessArguments(
        javascript()->Runtime(Runtime::kGetPropertyNamesFast, 1), 1);
    // TODO(dcarney): these next runtime calls should be removed in favour of
    //                a few simplified instructions.
    environment()->Push(obj);
    environment()->Push(cache_type);
    Node* cache_pair =
        ProcessArguments(javascript()->Runtime(Runtime::kForInInit, 2), 2);
    // cache_type may have been replaced.
    Node* cache_array = NewNode(common()->Projection(0), cache_pair);
    cache_type = NewNode(common()->Projection(1), cache_pair);
    environment()->Push(cache_type);
    environment()->Push(cache_array);
    Node* cache_length = ProcessArguments(
        javascript()->Runtime(Runtime::kForInCacheArrayLength, 2), 2);
    {
      // TODO(dcarney): this check is actually supposed to be for the
      //                empty enum case only.
      IfBuilder have_no_properties(this);
      Node* empty_array_cond = NewNode(javascript()->StrictEqual(),
                                       cache_length, jsgraph()->ZeroConstant());
      have_no_properties.If(empty_array_cond);
      have_no_properties.Then();
      // Pop obj and skip loop.
      environment()->Pop();
      have_no_properties.Else();
      {
        // Construct the rest of the environment.
        environment()->Push(cache_type);
        environment()->Push(cache_array);
        environment()->Push(cache_length);
        environment()->Push(jsgraph()->ZeroConstant());
        // PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
        LoopBuilder for_loop(this);
        for_loop.BeginLoop();
        // Check loop termination condition.
        Node* index = environment()->Peek(0);
        Node* exit_cond =
            NewNode(javascript()->LessThan(), index, cache_length);
        // TODO(jarin): provide real bailout id.
        BuildLazyBailout(exit_cond, BailoutId::None());
        for_loop.BreakUnless(exit_cond);
        // TODO(dcarney): this runtime call should be a handful of
        //                simplified instructions that
        //                basically produce
        //                    value = array[index]
        environment()->Push(obj);
        environment()->Push(cache_array);
        environment()->Push(cache_type);
        environment()->Push(index);
        Node* pair =
            ProcessArguments(javascript()->Runtime(Runtime::kForInNext, 4), 4);
        Node* value = NewNode(common()->Projection(0), pair);
        Node* should_filter = NewNode(common()->Projection(1), pair);
        environment()->Push(value);
        {
          // Test if FILTER_KEY needs to be called.
          IfBuilder test_should_filter(this);
          Node* should_filter_cond =
              NewNode(javascript()->StrictEqual(), should_filter,
                      jsgraph()->TrueConstant());
          test_should_filter.If(should_filter_cond);
          test_should_filter.Then();
          value = environment()->Pop();
          // TODO(dcarney): Better load from function context.
          // See comment in BuildLoadBuiltinsObject.
          Handle<JSFunction> function(JSFunction::cast(
              info()->context()->builtins()->javascript_builtin(
                  Builtins::FILTER_KEY)));
          // Callee.
          environment()->Push(jsgraph()->HeapConstant(function));
          // Receiver.
          environment()->Push(obj);
          // Args.
          environment()->Push(value);
          // result is either the string key or Smi(0) indicating the property
          // is gone.
          Node* res = ProcessArguments(
              javascript()->Call(3, NO_CALL_FUNCTION_FLAGS), 3);
          // TODO(jarin): provide real bailout id.
          BuildLazyBailout(res, BailoutId::None());
          Node* property_missing = NewNode(javascript()->StrictEqual(), res,
                                           jsgraph()->ZeroConstant());
          {
            IfBuilder is_property_missing(this);
            is_property_missing.If(property_missing);
            is_property_missing.Then();
            // Inc counter and continue.
            Node* index_inc =
                NewNode(javascript()->Add(), index, jsgraph()->OneConstant());
            environment()->Poke(0, index_inc);
            // TODO(jarin): provide real bailout id.
            BuildLazyBailout(index_inc, BailoutId::None());
            for_loop.Continue();
            is_property_missing.Else();
            is_property_missing.End();
          }
          // Replace 'value' in environment.
          environment()->Push(res);
          test_should_filter.Else();
          test_should_filter.End();
        }
        value = environment()->Pop();
        // Bind value and do loop body.
        VisitForInAssignment(stmt->each(), value);
        VisitIterationBody(stmt, &for_loop, 5);
        // Inc counter and continue.
        Node* index_inc =
            NewNode(javascript()->Add(), index, jsgraph()->OneConstant());
        environment()->Poke(0, index_inc);
        // TODO(jarin): provide real bailout id.
        BuildLazyBailout(index_inc, BailoutId::None());
        for_loop.EndBody();
        for_loop.EndLoop();
        environment()->Drop(5);
        // PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
      }
      have_no_properties.End();
    }
    is_null.End();
  }
  is_undefined.End();
}


void AstGraphBuilder::VisitForOfStatement(ForOfStatement* stmt) {
  VisitForValue(stmt->subject());
  environment()->Pop();
  // TODO(turbofan): create and use loop builder.
}


void AstGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) {
  UNREACHABLE();
}


void AstGraphBuilder::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
  UNREACHABLE();
}


void AstGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) {
  // TODO(turbofan): Do we really need a separate reloc-info for this?
  NewNode(javascript()->Runtime(Runtime::kDebugBreak, 0));
}


void AstGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) {
  Node* context = current_context();

  // Build a new shared function info if we cannot find one in the baseline
  // code. We also have a stack overflow if the recursive compilation did.
  Handle<SharedFunctionInfo> shared_info =
      SearchSharedFunctionInfo(info()->shared_info()->code(), expr);
  if (shared_info.is_null()) {
    shared_info = Compiler::BuildFunctionInfo(expr, info()->script(), info());
    CHECK(!shared_info.is_null());  // TODO(mstarzinger): Set stack overflow?
  }

  // Create node to instantiate a new closure.
  Node* info = jsgraph()->Constant(shared_info);
  Node* pretenure = expr->pretenure() ? jsgraph()->TrueConstant()
                                      : jsgraph()->FalseConstant();
  Operator* op = javascript()->Runtime(Runtime::kNewClosure, 3);
  Node* value = NewNode(op, context, info, pretenure);
  ast_context()->ProduceValue(value);
}


void AstGraphBuilder::VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) {
  UNREACHABLE();
}


void AstGraphBuilder::VisitConditional(Conditional* expr) {
  IfBuilder compare_if(this);
  VisitForTest(expr->condition());
  Node* condition = environment()->Pop();
  compare_if.If(condition);
  compare_if.Then();
  Visit(expr->then_expression());
  compare_if.Else();
  Visit(expr->else_expression());
  compare_if.End();
  ast_context()->ReplaceValue();
}


void AstGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
  Node* value = BuildVariableLoad(expr->var(), expr->id());
  ast_context()->ProduceValue(value);
}


void AstGraphBuilder::VisitLiteral(Literal* expr) {
  Node* value = jsgraph()->Constant(expr->value());
  ast_context()->ProduceValue(value);
}


void AstGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) {
  Handle<JSFunction> closure = info()->closure();

  // Create node to materialize a regular expression literal.
  Node* literals_array = jsgraph()->Constant(handle(closure->literals()));
  Node* literal_index = jsgraph()->Constant(expr->literal_index());
  Node* pattern = jsgraph()->Constant(expr->pattern());
  Node* flags = jsgraph()->Constant(expr->flags());
  Operator* op = javascript()->Runtime(Runtime::kMaterializeRegExpLiteral, 4);
  Node* literal = NewNode(op, literals_array, literal_index, pattern, flags);
  ast_context()->ProduceValue(literal);
}


void AstGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
  Handle<JSFunction> closure = info()->closure();

  // Create node to deep-copy the literal boilerplate.
  expr->BuildConstantProperties(isolate());
  Node* literals_array = jsgraph()->Constant(handle(closure->literals()));
  Node* literal_index = jsgraph()->Constant(expr->literal_index());
  Node* constants = jsgraph()->Constant(expr->constant_properties());
  Node* flags = jsgraph()->Constant(expr->ComputeFlags());
  Operator* op = javascript()->Runtime(Runtime::kCreateObjectLiteral, 4);
  Node* literal = NewNode(op, literals_array, literal_index, constants, flags);

  // The object is expected on the operand stack during computation of the
  // property values and is the value of the entire expression.
  environment()->Push(literal);

  // Mark all computed expressions that are bound to a key that is shadowed by
  // a later occurrence of the same key. For the marked expressions, no store
  // code is emitted.
  expr->CalculateEmitStore(zone());

  // Create nodes to store computed values into the literal.
  AccessorTable accessor_table(zone());
  for (int i = 0; i < expr->properties()->length(); i++) {
    ObjectLiteral::Property* property = expr->properties()->at(i);
    if (property->IsCompileTimeValue()) continue;

    Literal* key = property->key();
    switch (property->kind()) {
      case ObjectLiteral::Property::CONSTANT:
        UNREACHABLE();
      case ObjectLiteral::Property::MATERIALIZED_LITERAL:
        DCHECK(!CompileTimeValue::IsCompileTimeValue(property->value()));
      // Fall through.
      case ObjectLiteral::Property::COMPUTED: {
        // It is safe to use [[Put]] here because the boilerplate already
        // contains computed properties with an uninitialized value.
        if (key->value()->IsInternalizedString()) {
          if (property->emit_store()) {
            VisitForValue(property->value());
            Node* value = environment()->Pop();
            PrintableUnique<Name> name = MakeUnique(key->AsPropertyName());
            Node* store =
                NewNode(javascript()->StoreNamed(name), literal, value);
            BuildLazyBailout(store, key->id());
          } else {
            VisitForEffect(property->value());
          }
          break;
        }
        environment()->Push(literal);  // Duplicate receiver.
        VisitForValue(property->key());
        VisitForValue(property->value());
        Node* value = environment()->Pop();
        Node* key = environment()->Pop();
        Node* receiver = environment()->Pop();
        if (property->emit_store()) {
          Node* strict = jsgraph()->Constant(SLOPPY);
          Operator* op = javascript()->Runtime(Runtime::kSetProperty, 4);
          NewNode(op, receiver, key, value, strict);
        }
        break;
      }
      case ObjectLiteral::Property::PROTOTYPE: {
        environment()->Push(literal);  // Duplicate receiver.
        VisitForValue(property->value());
        Node* value = environment()->Pop();
        Node* receiver = environment()->Pop();
        if (property->emit_store()) {
          Operator* op = javascript()->Runtime(Runtime::kSetPrototype, 2);
          NewNode(op, receiver, value);
        }
        break;
      }
      case ObjectLiteral::Property::GETTER:
        accessor_table.lookup(key)->second->getter = property->value();
        break;
      case ObjectLiteral::Property::SETTER:
        accessor_table.lookup(key)->second->setter = property->value();
        break;
    }
  }

  // Create nodes to define accessors, using only a single call to the runtime
  // for each pair of corresponding getters and setters.
  for (AccessorTable::Iterator it = accessor_table.begin();
       it != accessor_table.end(); ++it) {
    VisitForValue(it->first);
    VisitForValueOrNull(it->second->getter);
    VisitForValueOrNull(it->second->setter);
    Node* setter = environment()->Pop();
    Node* getter = environment()->Pop();
    Node* name = environment()->Pop();
    Node* attr = jsgraph()->Constant(NONE);
    Operator* op =
        javascript()->Runtime(Runtime::kDefineAccessorPropertyUnchecked, 5);
    NewNode(op, literal, name, getter, setter, attr);
  }

  // Transform literals that contain functions to fast properties.
  if (expr->has_function()) {
    Operator* op = javascript()->Runtime(Runtime::kToFastProperties, 1);
    NewNode(op, literal);
  }

  ast_context()->ProduceValue(environment()->Pop());
}


void AstGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
  Handle<JSFunction> closure = info()->closure();

  // Create node to deep-copy the literal boilerplate.
  expr->BuildConstantElements(isolate());
  Node* literals_array = jsgraph()->Constant(handle(closure->literals()));
  Node* literal_index = jsgraph()->Constant(expr->literal_index());
  Node* constants = jsgraph()->Constant(expr->constant_elements());
  Node* flags = jsgraph()->Constant(expr->ComputeFlags());
  Operator* op = javascript()->Runtime(Runtime::kCreateArrayLiteral, 4);
  Node* literal = NewNode(op, literals_array, literal_index, constants, flags);

  // The array and the literal index are both expected on the operand stack
  // during computation of the element values.
  environment()->Push(literal);
  environment()->Push(literal_index);

  // Create nodes to evaluate all the non-constant subexpressions and to store
  // them into the newly cloned array.
  for (int i = 0; i < expr->values()->length(); i++) {
    Expression* subexpr = expr->values()->at(i);
    if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue;

    VisitForValue(subexpr);
    Node* value = environment()->Pop();
    Node* index = jsgraph()->Constant(i);
    Node* store = NewNode(javascript()->StoreProperty(), literal, index, value);
    BuildLazyBailout(store, expr->GetIdForElement(i));
  }

  environment()->Pop();  // Array literal index.
  ast_context()->ProduceValue(environment()->Pop());
}


void AstGraphBuilder::VisitForInAssignment(Expression* expr, Node* value) {
  DCHECK(expr->IsValidReferenceExpression());

  // Left-hand side can only be a property, a global or a variable slot.
  Property* property = expr->AsProperty();
  LhsKind assign_type = DetermineLhsKind(expr);

  // Evaluate LHS expression and store the value.
  switch (assign_type) {
    case VARIABLE: {
      Variable* var = expr->AsVariableProxy()->var();
      // TODO(jarin) Fill in the correct bailout id.
      BuildVariableAssignment(var, value, Token::ASSIGN, BailoutId::None());
      break;
    }
    case NAMED_PROPERTY: {
      environment()->Push(value);
      VisitForValue(property->obj());
      Node* object = environment()->Pop();
      value = environment()->Pop();
      PrintableUnique<Name> name =
          MakeUnique(property->key()->AsLiteral()->AsPropertyName());
      Node* store = NewNode(javascript()->StoreNamed(name), object, value);
      // TODO(jarin) Fill in the correct bailout id.
      BuildLazyBailout(store, BailoutId::None());
      break;
    }
    case KEYED_PROPERTY: {
      environment()->Push(value);
      VisitForValue(property->obj());
      VisitForValue(property->key());
      Node* key = environment()->Pop();
      Node* object = environment()->Pop();
      value = environment()->Pop();
      Node* store = NewNode(javascript()->StoreProperty(), object, key, value);
      // TODO(jarin) Fill in the correct bailout id.
      BuildLazyBailout(store, BailoutId::None());
      break;
    }
  }
}


void AstGraphBuilder::VisitAssignment(Assignment* expr) {
  DCHECK(expr->target()->IsValidReferenceExpression());

  // Left-hand side can only be a property, a global or a variable slot.
  Property* property = expr->target()->AsProperty();
  LhsKind assign_type = DetermineLhsKind(expr->target());

  // Evaluate LHS expression.
  switch (assign_type) {
    case VARIABLE:
      // Nothing to do here.
      break;
    case NAMED_PROPERTY:
      VisitForValue(property->obj());
      break;
    case KEYED_PROPERTY: {
      VisitForValue(property->obj());
      VisitForValue(property->key());
      break;
    }
  }

  // Evaluate the value and potentially handle compound assignments by loading
  // the left-hand side value and performing a binary operation.
  if (expr->is_compound()) {
    Node* old_value = NULL;
    switch (assign_type) {
      case VARIABLE: {
        Variable* variable = expr->target()->AsVariableProxy()->var();
        old_value = BuildVariableLoad(variable, expr->target()->id());
        break;
      }
      case NAMED_PROPERTY: {
        Node* object = environment()->Top();
        PrintableUnique<Name> name =
            MakeUnique(property->key()->AsLiteral()->AsPropertyName());
        old_value = NewNode(javascript()->LoadNamed(name), object);
        BuildLazyBailoutWithPushedNode(old_value, property->LoadId());
        break;
      }
      case KEYED_PROPERTY: {
        Node* key = environment()->Top();
        Node* object = environment()->Peek(1);
        old_value = NewNode(javascript()->LoadProperty(), object, key);
        BuildLazyBailoutWithPushedNode(old_value, property->LoadId());
        break;
      }
    }
    environment()->Push(old_value);
    VisitForValue(expr->value());
    Node* right = environment()->Pop();
    Node* left = environment()->Pop();
    Node* value = BuildBinaryOp(left, right, expr->binary_op());
    environment()->Push(value);
    BuildLazyBailout(value, expr->binary_operation()->id());
  } else {
    VisitForValue(expr->value());
  }

  // Store the value.
  Node* value = environment()->Pop();
  switch (assign_type) {
    case VARIABLE: {
      Variable* variable = expr->target()->AsVariableProxy()->var();
      BuildVariableAssignment(variable, value, expr->op(),
                              expr->AssignmentId());
      break;
    }
    case NAMED_PROPERTY: {
      Node* object = environment()->Pop();
      PrintableUnique<Name> name =
          MakeUnique(property->key()->AsLiteral()->AsPropertyName());
      Node* store = NewNode(javascript()->StoreNamed(name), object, value);
      BuildLazyBailout(store, expr->AssignmentId());
      break;
    }
    case KEYED_PROPERTY: {
      Node* key = environment()->Pop();
      Node* object = environment()->Pop();
      Node* store = NewNode(javascript()->StoreProperty(), object, key, value);
      BuildLazyBailout(store, expr->AssignmentId());
      break;
    }
  }

  ast_context()->ProduceValue(value);
}


void AstGraphBuilder::VisitYield(Yield* expr) {
  VisitForValue(expr->generator_object());
  VisitForValue(expr->expression());
  environment()->Pop();
  environment()->Pop();
  // TODO(turbofan): VisitYield
  ast_context()->ProduceValue(jsgraph()->UndefinedConstant());
}


void AstGraphBuilder::VisitThrow(Throw* expr) {
  VisitForValue(expr->exception());
  Node* exception = environment()->Pop();
  Operator* op = javascript()->Runtime(Runtime::kThrow, 1);
  Node* value = NewNode(op, exception);
  ast_context()->ProduceValue(value);
}


void AstGraphBuilder::VisitProperty(Property* expr) {
  Node* value;
  if (expr->key()->IsPropertyName()) {
    VisitForValue(expr->obj());
    Node* object = environment()->Pop();
    PrintableUnique<Name> name =
        MakeUnique(expr->key()->AsLiteral()->AsPropertyName());
    value = NewNode(javascript()->LoadNamed(name), object);
  } else {
    VisitForValue(expr->obj());
    VisitForValue(expr->key());
    Node* key = environment()->Pop();
    Node* object = environment()->Pop();
    value = NewNode(javascript()->LoadProperty(), object, key);
  }
  ast_context()->ProduceValueWithLazyBailout(value);
}


void AstGraphBuilder::VisitCall(Call* expr) {
  Expression* callee = expr->expression();
  Call::CallType call_type = expr->GetCallType(isolate());

  // Prepare the callee and the receiver to the function call. This depends on
  // the semantics of the underlying call type.
  CallFunctionFlags flags = NO_CALL_FUNCTION_FLAGS;
  Node* receiver_value = NULL;
  Node* callee_value = NULL;
  bool possibly_eval = false;
  switch (call_type) {
    case Call::GLOBAL_CALL: {
      Variable* variable = callee->AsVariableProxy()->var();
      callee_value = BuildVariableLoad(variable, expr->expression()->id());
      receiver_value = jsgraph()->UndefinedConstant();
      break;
    }
    case Call::LOOKUP_SLOT_CALL: {
      Variable* variable = callee->AsVariableProxy()->var();
      DCHECK(variable->location() == Variable::LOOKUP);
      Node* name = jsgraph()->Constant(variable->name());
      Operator* op = javascript()->Runtime(Runtime::kLoadLookupSlot, 2);
      Node* pair = NewNode(op, current_context(), name);
      callee_value = NewNode(common()->Projection(0), pair);
      receiver_value = NewNode(common()->Projection(1), pair);
      break;
    }
    case Call::PROPERTY_CALL: {
      Property* property = callee->AsProperty();
      VisitForValue(property->obj());
      Node* object = environment()->Top();
      if (property->key()->IsPropertyName()) {
        PrintableUnique<Name> name =
            MakeUnique(property->key()->AsLiteral()->AsPropertyName());
        callee_value = NewNode(javascript()->LoadNamed(name), object);
      } else {
        VisitForValue(property->key());
        Node* key = environment()->Pop();
        callee_value = NewNode(javascript()->LoadProperty(), object, key);
      }
      BuildLazyBailoutWithPushedNode(callee_value, property->LoadId());
      receiver_value = environment()->Pop();
      // Note that a PROPERTY_CALL requires the receiver to be wrapped into an
      // object for sloppy callees. This could also be modeled explicitly here,
      // thereby obsoleting the need for a flag to the call operator.
      flags = CALL_AS_METHOD;
      break;
    }
    case Call::POSSIBLY_EVAL_CALL:
      possibly_eval = true;
    // Fall through.
    case Call::OTHER_CALL:
      VisitForValue(callee);
      callee_value = environment()->Pop();
      receiver_value = jsgraph()->UndefinedConstant();
      break;
  }

  // The callee and the receiver both have to be pushed onto the operand stack
  // before arguments are being evaluated.
  environment()->Push(callee_value);
  environment()->Push(receiver_value);

  // Evaluate all arguments to the function call,
  ZoneList<Expression*>* args = expr->arguments();
  VisitForValues(args);

  // Resolve callee and receiver for a potential direct eval call. This block
  // will mutate the callee and receiver values pushed onto the environment.
  if (possibly_eval && args->length() > 0) {
    int arg_count = args->length();

    // Extract callee and source string from the environment.
    Node* callee = environment()->Peek(arg_count + 1);
    Node* source = environment()->Peek(arg_count - 1);

    // Create node to ask for help resolving potential eval call. This will
    // provide a fully resolved callee and the corresponding receiver.
    Node* receiver = environment()->Lookup(info()->scope()->receiver());
    Node* strict = jsgraph()->Constant(strict_mode());
    Node* position = jsgraph()->Constant(info()->scope()->start_position());
    Operator* op =
        javascript()->Runtime(Runtime::kResolvePossiblyDirectEval, 5);
    Node* pair = NewNode(op, callee, source, receiver, strict, position);
    Node* new_callee = NewNode(common()->Projection(0), pair);
    Node* new_receiver = NewNode(common()->Projection(1), pair);

    // Patch callee and receiver on the environment.
    environment()->Poke(arg_count + 1, new_callee);
    environment()->Poke(arg_count + 0, new_receiver);
  }

  // Create node to perform the function call.
  Operator* call = javascript()->Call(args->length() + 2, flags);
  Node* value = ProcessArguments(call, args->length() + 2);
  ast_context()->ProduceValueWithLazyBailout(value);
}


void AstGraphBuilder::VisitCallNew(CallNew* expr) {
  VisitForValue(expr->expression());

  // Evaluate all arguments to the construct call.
  ZoneList<Expression*>* args = expr->arguments();
  VisitForValues(args);

  // Create node to perform the construct call.
  Operator* call = javascript()->CallNew(args->length() + 1);
  Node* value = ProcessArguments(call, args->length() + 1);
  ast_context()->ProduceValueWithLazyBailout(value);
}


void AstGraphBuilder::VisitCallJSRuntime(CallRuntime* expr) {
  Handle<String> name = expr->name();

  // The callee and the receiver both have to be pushed onto the operand stack
  // before arguments are being evaluated.
  CallFunctionFlags flags = NO_CALL_FUNCTION_FLAGS;
  Node* receiver_value = BuildLoadBuiltinsObject();
  PrintableUnique<String> unique = MakeUnique(name);
  Node* callee_value = NewNode(javascript()->LoadNamed(unique), receiver_value);
  environment()->Push(callee_value);
  // TODO(jarin): Find/create a bailout id to deoptimize to (crankshaft
  // refuses to optimize functions with jsruntime calls).
  BuildLazyBailout(callee_value, BailoutId::None());
  environment()->Push(receiver_value);

  // Evaluate all arguments to the JS runtime call.
  ZoneList<Expression*>* args = expr->arguments();
  VisitForValues(args);

  // Create node to perform the JS runtime call.
  Operator* call = javascript()->Call(args->length() + 2, flags);
  Node* value = ProcessArguments(call, args->length() + 2);
  ast_context()->ProduceValueWithLazyBailout(value);
}


void AstGraphBuilder::VisitCallRuntime(CallRuntime* expr) {
  const Runtime::Function* function = expr->function();

  // Handle calls to runtime functions implemented in JavaScript separately as
  // the call follows JavaScript ABI and the callee is statically unknown.
  if (expr->is_jsruntime()) {
    DCHECK(function == NULL && expr->name()->length() > 0);
    return VisitCallJSRuntime(expr);
  }

  // Evaluate all arguments to the runtime call.
  ZoneList<Expression*>* args = expr->arguments();
  VisitForValues(args);

  // Create node to perform the runtime call.
  Runtime::FunctionId functionId = function->function_id;
  Operator* call = javascript()->Runtime(functionId, args->length());
  Node* value = ProcessArguments(call, args->length());
  ast_context()->ProduceValueWithLazyBailout(value);
}


void AstGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) {
  switch (expr->op()) {
    case Token::DELETE:
      return VisitDelete(expr);
    case Token::VOID:
      return VisitVoid(expr);
    case Token::TYPEOF:
      return VisitTypeof(expr);
    case Token::NOT:
      return VisitNot(expr);
    default:
      UNREACHABLE();
  }
}


void AstGraphBuilder::VisitCountOperation(CountOperation* expr) {
  DCHECK(expr->expression()->IsValidReferenceExpression());

  // Left-hand side can only be a property, a global or a variable slot.
  Property* property = expr->expression()->AsProperty();
  LhsKind assign_type = DetermineLhsKind(expr->expression());

  // Reserve space for result of postfix operation.
  bool is_postfix = expr->is_postfix() && !ast_context()->IsEffect();
  if (is_postfix) environment()->Push(jsgraph()->UndefinedConstant());

  // Evaluate LHS expression and get old value.
  Node* old_value = NULL;
  int stack_depth = -1;
  switch (assign_type) {
    case VARIABLE: {
      Variable* variable = expr->expression()->AsVariableProxy()->var();
      old_value = BuildVariableLoad(variable, expr->expression()->id());
      stack_depth = 0;
      break;
    }
    case NAMED_PROPERTY: {
      VisitForValue(property->obj());
      Node* object = environment()->Top();
      PrintableUnique<Name> name =
          MakeUnique(property->key()->AsLiteral()->AsPropertyName());
      old_value = NewNode(javascript()->LoadNamed(name), object);
      BuildLazyBailoutWithPushedNode(old_value, property->LoadId());
      stack_depth = 1;
      break;
    }
    case KEYED_PROPERTY: {
      VisitForValue(property->obj());
      VisitForValue(property->key());
      Node* key = environment()->Top();
      Node* object = environment()->Peek(1);
      old_value = NewNode(javascript()->LoadProperty(), object, key);
      BuildLazyBailoutWithPushedNode(old_value, property->LoadId());
      stack_depth = 2;
      break;
    }
  }

  // Convert old value into a number.
  old_value = NewNode(javascript()->ToNumber(), old_value);

  // Save result for postfix expressions at correct stack depth.
  if (is_postfix) environment()->Poke(stack_depth, old_value);

  // Create node to perform +1/-1 operation.
  Node* value =
      BuildBinaryOp(old_value, jsgraph()->OneConstant(), expr->binary_op());
  // TODO(jarin) Insert proper bailout id here (will need to change
  // full code generator).
  BuildLazyBailout(value, BailoutId::None());

  // Store the value.
  switch (assign_type) {
    case VARIABLE: {
      Variable* variable = expr->expression()->AsVariableProxy()->var();
      BuildVariableAssignment(variable, value, expr->op(),
                              expr->AssignmentId());
      break;
    }
    case NAMED_PROPERTY: {
      Node* object = environment()->Pop();
      PrintableUnique<Name> name =
          MakeUnique(property->key()->AsLiteral()->AsPropertyName());
      Node* store = NewNode(javascript()->StoreNamed(name), object, value);
      BuildLazyBailout(store, expr->AssignmentId());
      break;
    }
    case KEYED_PROPERTY: {
      Node* key = environment()->Pop();
      Node* object = environment()->Pop();
      Node* store = NewNode(javascript()->StoreProperty(), object, key, value);
      BuildLazyBailout(store, expr->AssignmentId());
      break;
    }
  }

  // Restore old value for postfix expressions.
  if (is_postfix) value = environment()->Pop();

  ast_context()->ProduceValue(value);
}


void AstGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) {
  switch (expr->op()) {
    case Token::COMMA:
      return VisitComma(expr);
    case Token::OR:
    case Token::AND:
      return VisitLogicalExpression(expr);
    default: {
      VisitForValue(expr->left());
      VisitForValue(expr->right());
      Node* right = environment()->Pop();
      Node* left = environment()->Pop();
      Node* value = BuildBinaryOp(left, right, expr->op());
      ast_context()->ProduceValueWithLazyBailout(value);
    }
  }
}


void AstGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
  Operator* op;
  switch (expr->op()) {
    case Token::EQ:
      op = javascript()->Equal();
      break;
    case Token::NE:
      op = javascript()->NotEqual();
      break;
    case Token::EQ_STRICT:
      op = javascript()->StrictEqual();
      break;
    case Token::NE_STRICT:
      op = javascript()->StrictNotEqual();
      break;
    case Token::LT:
      op = javascript()->LessThan();
      break;
    case Token::GT:
      op = javascript()->GreaterThan();
      break;
    case Token::LTE:
      op = javascript()->LessThanOrEqual();
      break;
    case Token::GTE:
      op = javascript()->GreaterThanOrEqual();
      break;
    case Token::INSTANCEOF:
      op = javascript()->InstanceOf();
      break;
    case Token::IN:
      op = javascript()->HasProperty();
      break;
    default:
      op = NULL;
      UNREACHABLE();
  }
  VisitForValue(expr->left());
  VisitForValue(expr->right());
  Node* right = environment()->Pop();
  Node* left = environment()->Pop();
  Node* value = NewNode(op, left, right);
  ast_context()->ProduceValue(value);

  BuildLazyBailout(value, expr->id());
}


void AstGraphBuilder::VisitThisFunction(ThisFunction* expr) {
  Node* value = GetFunctionClosure();
  ast_context()->ProduceValue(value);
}


void AstGraphBuilder::VisitCaseClause(CaseClause* expr) { UNREACHABLE(); }


void AstGraphBuilder::VisitDeclarations(ZoneList<Declaration*>* declarations) {
  DCHECK(globals()->is_empty());
  AstVisitor::VisitDeclarations(declarations);
  if (globals()->is_empty()) return;
  Handle<FixedArray> data =
      isolate()->factory()->NewFixedArray(globals()->length(), TENURED);
  for (int i = 0; i < globals()->length(); ++i) data->set(i, *globals()->at(i));
  int encoded_flags = DeclareGlobalsEvalFlag::encode(info()->is_eval()) |
                      DeclareGlobalsNativeFlag::encode(info()->is_native()) |
                      DeclareGlobalsStrictMode::encode(info()->strict_mode());
  Node* flags = jsgraph()->Constant(encoded_flags);
  Node* pairs = jsgraph()->Constant(data);
  Operator* op = javascript()->Runtime(Runtime::kDeclareGlobals, 3);
  NewNode(op, current_context(), pairs, flags);
  globals()->Rewind(0);
}


void AstGraphBuilder::VisitIfNotNull(Statement* stmt) {
  if (stmt == NULL) return;
  Visit(stmt);
}


void AstGraphBuilder::VisitIterationBody(IterationStatement* stmt,
                                         LoopBuilder* loop, int drop_extra) {
  BreakableScope scope(this, stmt, loop, drop_extra);
  Visit(stmt->body());
}


void AstGraphBuilder::VisitDelete(UnaryOperation* expr) {
  Node* value;
  if (expr->expression()->IsVariableProxy()) {
    // Delete of an unqualified identifier is only allowed in classic mode but
    // deleting "this" is allowed in all language modes.
    Variable* variable = expr->expression()->AsVariableProxy()->var();
    DCHECK(strict_mode() == SLOPPY || variable->is_this());
    value = BuildVariableDelete(variable);
  } else if (expr->expression()->IsProperty()) {
    Property* property = expr->expression()->AsProperty();
    VisitForValue(property->obj());
    VisitForValue(property->key());
    Node* key = environment()->Pop();
    Node* object = environment()->Pop();
    value = NewNode(javascript()->DeleteProperty(strict_mode()), object, key);
  } else {
    VisitForEffect(expr->expression());
    value = jsgraph()->TrueConstant();
  }
  ast_context()->ProduceValue(value);
}


void AstGraphBuilder::VisitVoid(UnaryOperation* expr) {
  VisitForEffect(expr->expression());
  Node* value = jsgraph()->UndefinedConstant();
  ast_context()->ProduceValue(value);
}


void AstGraphBuilder::VisitTypeof(UnaryOperation* expr) {
  Node* operand;
  if (expr->expression()->IsVariableProxy()) {
    // Typeof does not throw a reference error on global variables, hence we
    // perform a non-contextual load in case the operand is a variable proxy.
    Variable* variable = expr->expression()->AsVariableProxy()->var();
    operand =
        BuildVariableLoad(variable, expr->expression()->id(), NOT_CONTEXTUAL);
  } else {
    VisitForValue(expr->expression());
    operand = environment()->Pop();
  }
  Node* value = NewNode(javascript()->TypeOf(), operand);
  ast_context()->ProduceValue(value);
}


void AstGraphBuilder::VisitNot(UnaryOperation* expr) {
  VisitForValue(expr->expression());
  Node* operand = environment()->Pop();
  // TODO(mstarzinger): Possible optimization when we are in effect context.
  Node* value = NewNode(javascript()->UnaryNot(), operand);
  ast_context()->ProduceValue(value);
}


void AstGraphBuilder::VisitComma(BinaryOperation* expr) {
  VisitForEffect(expr->left());
  Visit(expr->right());
  ast_context()->ReplaceValue();
}


void AstGraphBuilder::VisitLogicalExpression(BinaryOperation* expr) {
  bool is_logical_and = expr->op() == Token::AND;
  IfBuilder compare_if(this);
  VisitForValue(expr->left());
  Node* condition = environment()->Top();
  compare_if.If(BuildToBoolean(condition));
  compare_if.Then();
  if (is_logical_and) {
    environment()->Pop();
    Visit(expr->right());
  } else if (ast_context()->IsEffect()) {
    environment()->Pop();
  }
  compare_if.Else();
  if (!is_logical_and) {
    environment()->Pop();
    Visit(expr->right());
  } else if (ast_context()->IsEffect()) {
    environment()->Pop();
  }
  compare_if.End();
  ast_context()->ReplaceValue();
}


Node* AstGraphBuilder::ProcessArguments(Operator* op, int arity) {
  DCHECK(environment()->stack_height() >= arity);
  Node** all = info()->zone()->NewArray<Node*>(arity);  // XXX: alloca?
  for (int i = arity - 1; i >= 0; --i) {
    all[i] = environment()->Pop();
  }
  Node* value = NewNode(op, arity, all);
  return value;
}


Node* AstGraphBuilder::BuildLocalFunctionContext(Node* context, Node* closure) {
  int heap_slots = info()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
  if (heap_slots <= 0) return context;
  set_current_context(context);

  // Allocate a new local context.
  Operator* op = javascript()->CreateFunctionContext();
  Node* local_context = NewNode(op, closure);
  set_current_context(local_context);

  // Copy parameters into context if necessary.
  int num_parameters = info()->scope()->num_parameters();
  for (int i = 0; i < num_parameters; i++) {
    Variable* variable = info()->scope()->parameter(i);
    if (!variable->IsContextSlot()) continue;
    // Temporary parameter node. The parameter indices are shifted by 1
    // (receiver is parameter index -1 but environment index 0).
    Node* parameter = NewNode(common()->Parameter(i + 1), graph()->start());
    // Context variable (at bottom of the context chain).
    DCHECK_EQ(0, info()->scope()->ContextChainLength(variable->scope()));
    Operator* op = javascript()->StoreContext(0, variable->index());
    NewNode(op, local_context, parameter);
  }

  return local_context;
}


Node* AstGraphBuilder::BuildArgumentsObject(Variable* arguments) {
  if (arguments == NULL) return NULL;

  // Allocate and initialize a new arguments object.
  Node* callee = GetFunctionClosure();
  Operator* op = javascript()->Runtime(Runtime::kNewArguments, 1);
  Node* object = NewNode(op, callee);

  // Assign the object to the arguments variable.
  DCHECK(arguments->IsContextSlot() || arguments->IsStackAllocated());
  // This should never lazy deopt, so it is fine to send invalid bailout id.
  BuildVariableAssignment(arguments, object, Token::ASSIGN, BailoutId::None());

  return object;
}


Node* AstGraphBuilder::BuildHoleCheckSilent(Node* value, Node* for_hole,
                                            Node* not_hole) {
  IfBuilder hole_check(this);
  Node* the_hole = jsgraph()->TheHoleConstant();
  Node* check = NewNode(javascript()->StrictEqual(), value, the_hole);
  hole_check.If(check);
  hole_check.Then();
  environment()->Push(for_hole);
  hole_check.Else();
  environment()->Push(not_hole);
  hole_check.End();
  return environment()->Pop();
}


Node* AstGraphBuilder::BuildHoleCheckThrow(Node* value, Variable* variable,
                                           Node* not_hole) {
  IfBuilder hole_check(this);
  Node* the_hole = jsgraph()->TheHoleConstant();
  Node* check = NewNode(javascript()->StrictEqual(), value, the_hole);
  hole_check.If(check);
  hole_check.Then();
  environment()->Push(BuildThrowReferenceError(variable));
  hole_check.Else();
  environment()->Push(not_hole);
  hole_check.End();
  return environment()->Pop();
}


Node* AstGraphBuilder::BuildVariableLoad(Variable* variable,
                                         BailoutId bailout_id,
                                         ContextualMode contextual_mode) {
  Node* the_hole = jsgraph()->TheHoleConstant();
  VariableMode mode = variable->mode();
  switch (variable->location()) {
    case Variable::UNALLOCATED: {
      // Global var, const, or let variable.
      Node* global = BuildLoadGlobalObject();
      PrintableUnique<Name> name = MakeUnique(variable->name());
      Operator* op = javascript()->LoadNamed(name, contextual_mode);
      Node* node = NewNode(op, global);
      BuildLazyBailoutWithPushedNode(node, bailout_id);
      return node;
    }
    case Variable::PARAMETER:
    case Variable::LOCAL: {
      // Local var, const, or let variable.
      Node* value = environment()->Lookup(variable);
      if (mode == CONST_LEGACY) {
        // Perform check for uninitialized legacy const variables.
        if (value->op() == the_hole->op()) {
          value = jsgraph()->UndefinedConstant();
        } else if (value->opcode() == IrOpcode::kPhi) {
          Node* undefined = jsgraph()->UndefinedConstant();
          value = BuildHoleCheckSilent(value, undefined, value);
        }
      } else if (mode == LET || mode == CONST) {
        // Perform check for uninitialized let/const variables.
        if (value->op() == the_hole->op()) {
          value = BuildThrowReferenceError(variable);
        } else if (value->opcode() == IrOpcode::kPhi) {
          value = BuildHoleCheckThrow(value, variable, value);
        }
      }
      return value;
    }
    case Variable::CONTEXT: {
      // Context variable (potentially up the context chain).
      int depth = current_scope()->ContextChainLength(variable->scope());
      bool immutable = variable->maybe_assigned() == kNotAssigned;
      Operator* op =
          javascript()->LoadContext(depth, variable->index(), immutable);
      Node* value = NewNode(op, current_context());
      // TODO(titzer): initialization checks are redundant for already
      // initialized immutable context loads, but only specialization knows.
      // Maybe specializer should be a parameter to the graph builder?
      if (mode == CONST_LEGACY) {
        // Perform check for uninitialized legacy const variables.
        Node* undefined = jsgraph()->UndefinedConstant();
        value = BuildHoleCheckSilent(value, undefined, value);
      } else if (mode == LET || mode == CONST) {
        // Perform check for uninitialized let/const variables.
        value = BuildHoleCheckThrow(value, variable, value);
      }
      return value;
    }
    case Variable::LOOKUP: {
      // Dynamic lookup of context variable (anywhere in the chain).
      Node* name = jsgraph()->Constant(variable->name());
      Runtime::FunctionId function_id =
          (contextual_mode == CONTEXTUAL)
              ? Runtime::kLoadLookupSlot
              : Runtime::kLoadLookupSlotNoReferenceError;
      Operator* op = javascript()->Runtime(function_id, 2);
      Node* pair = NewNode(op, current_context(), name);
      return NewNode(common()->Projection(0), pair);
    }
  }
  UNREACHABLE();
  return NULL;
}


Node* AstGraphBuilder::BuildVariableDelete(Variable* variable) {
  switch (variable->location()) {
    case Variable::UNALLOCATED: {
      // Global var, const, or let variable.
      Node* global = BuildLoadGlobalObject();
      Node* name = jsgraph()->Constant(variable->name());
      Operator* op = javascript()->DeleteProperty(strict_mode());
      return NewNode(op, global, name);
    }
    case Variable::PARAMETER:
    case Variable::LOCAL:
    case Variable::CONTEXT:
      // Local var, const, or let variable or context variable.
      return variable->is_this() ? jsgraph()->TrueConstant()
                                 : jsgraph()->FalseConstant();
    case Variable::LOOKUP: {
      // Dynamic lookup of context variable (anywhere in the chain).
      Node* name = jsgraph()->Constant(variable->name());
      Operator* op = javascript()->Runtime(Runtime::kDeleteLookupSlot, 2);
      return NewNode(op, current_context(), name);
    }
  }
  UNREACHABLE();
  return NULL;
}


Node* AstGraphBuilder::BuildVariableAssignment(Variable* variable, Node* value,
                                               Token::Value op,
                                               BailoutId bailout_id) {
  Node* the_hole = jsgraph()->TheHoleConstant();
  VariableMode mode = variable->mode();
  switch (variable->location()) {
    case Variable::UNALLOCATED: {
      // Global var, const, or let variable.
      Node* global = BuildLoadGlobalObject();
      PrintableUnique<Name> name = MakeUnique(variable->name());
      Operator* op = javascript()->StoreNamed(name);
      Node* store = NewNode(op, global, value);
      BuildLazyBailout(store, bailout_id);
      return store;
    }
    case Variable::PARAMETER:
    case Variable::LOCAL:
      // Local var, const, or let variable.
      if (mode == CONST_LEGACY && op == Token::INIT_CONST_LEGACY) {
        // Perform an initialization check for legacy const variables.
        Node* current = environment()->Lookup(variable);
        if (current->op() != the_hole->op()) {
          value = BuildHoleCheckSilent(current, value, current);
        }
      } else if (mode == CONST_LEGACY && op != Token::INIT_CONST_LEGACY) {
        // Non-initializing assignments to legacy const is ignored.
        return value;
      } else if (mode == LET && op != Token::INIT_LET) {
        // Perform an initialization check for let declared variables.
        // Also note that the dynamic hole-check is only done to ensure that
        // this does not break in the presence of do-expressions within the
        // temporal dead zone of a let declared variable.
        Node* current = environment()->Lookup(variable);
        if (current->op() == the_hole->op()) {
          value = BuildThrowReferenceError(variable);
        } else if (value->opcode() == IrOpcode::kPhi) {
          value = BuildHoleCheckThrow(current, variable, value);
        }
      } else if (mode == CONST && op != Token::INIT_CONST) {
        // All assignments to const variables are early errors.
        UNREACHABLE();
      }
      environment()->Bind(variable, value);
      return value;
    case Variable::CONTEXT: {
      // Context variable (potentially up the context chain).
      int depth = current_scope()->ContextChainLength(variable->scope());
      if (mode == CONST_LEGACY && op == Token::INIT_CONST_LEGACY) {
        // Perform an initialization check for legacy const variables.
        Operator* op =
            javascript()->LoadContext(depth, variable->index(), false);
        Node* current = NewNode(op, current_context());
        value = BuildHoleCheckSilent(current, value, current);
      } else if (mode == CONST_LEGACY && op != Token::INIT_CONST_LEGACY) {
        // Non-initializing assignments to legacy const is ignored.
        return value;
      } else if (mode == LET && op != Token::INIT_LET) {
        // Perform an initialization check for let declared variables.
        Operator* op =
            javascript()->LoadContext(depth, variable->index(), false);
        Node* current = NewNode(op, current_context());
        value = BuildHoleCheckThrow(current, variable, value);
      } else if (mode == CONST && op != Token::INIT_CONST) {
        // All assignments to const variables are early errors.
        UNREACHABLE();
      }
      Operator* op = javascript()->StoreContext(depth, variable->index());
      return NewNode(op, current_context(), value);
    }
    case Variable::LOOKUP: {
      // Dynamic lookup of context variable (anywhere in the chain).
      Node* name = jsgraph()->Constant(variable->name());
      Node* strict = jsgraph()->Constant(strict_mode());
      // TODO(mstarzinger): Use Runtime::kInitializeLegacyConstLookupSlot for
      // initializations of const declarations.
      Operator* op = javascript()->Runtime(Runtime::kStoreLookupSlot, 4);
      return NewNode(op, value, current_context(), name, strict);
    }
  }
  UNREACHABLE();
  return NULL;
}


Node* AstGraphBuilder::BuildLoadBuiltinsObject() {
  // TODO(mstarzinger): Better load from function context, otherwise optimized
  // code cannot be shared across native contexts.
  return jsgraph()->Constant(handle(info()->context()->builtins()));
}


Node* AstGraphBuilder::BuildLoadGlobalObject() {
#if 0
  Node* context = GetFunctionContext();
  // TODO(mstarzinger): Use mid-level operator on FixedArray instead of the
  // JS-level operator that targets JSObject.
  Node* index = jsgraph()->Constant(Context::GLOBAL_OBJECT_INDEX);
  return NewNode(javascript()->LoadProperty(), context, index);
#else
  // TODO(mstarzinger): Better load from function context, otherwise optimized
  // code cannot be shared across native contexts. See unused code above.
  return jsgraph()->Constant(handle(info()->context()->global_object()));
#endif
}


Node* AstGraphBuilder::BuildToBoolean(Node* value) {
  // TODO(mstarzinger): Possible optimization is to NOP for boolean values.
  return NewNode(javascript()->ToBoolean(), value);
}


Node* AstGraphBuilder::BuildThrowReferenceError(Variable* variable) {
  // TODO(mstarzinger): Should be unified with the VisitThrow implementation.
  Node* variable_name = jsgraph()->Constant(variable->name());
  Operator* op = javascript()->Runtime(Runtime::kThrowReferenceError, 1);
  return NewNode(op, variable_name);
}


Node* AstGraphBuilder::BuildBinaryOp(Node* left, Node* right, Token::Value op) {
  Operator* js_op;
  switch (op) {
    case Token::BIT_OR:
      js_op = javascript()->BitwiseOr();
      break;
    case Token::BIT_AND:
      js_op = javascript()->BitwiseAnd();
      break;
    case Token::BIT_XOR:
      js_op = javascript()->BitwiseXor();
      break;
    case Token::SHL:
      js_op = javascript()->ShiftLeft();
      break;
    case Token::SAR:
      js_op = javascript()->ShiftRight();
      break;
    case Token::SHR:
      js_op = javascript()->ShiftRightLogical();
      break;
    case Token::ADD:
      js_op = javascript()->Add();
      break;
    case Token::SUB:
      js_op = javascript()->Subtract();
      break;
    case Token::MUL:
      js_op = javascript()->Multiply();
      break;
    case Token::DIV:
      js_op = javascript()->Divide();
      break;
    case Token::MOD:
      js_op = javascript()->Modulus();
      break;
    default:
      UNREACHABLE();
      js_op = NULL;
  }
  return NewNode(js_op, left, right);
}


void AstGraphBuilder::BuildLazyBailout(Node* node, BailoutId ast_id) {
  if (OperatorProperties::CanLazilyDeoptimize(node->op())) {
    // The deopting node should have an outgoing control dependency.
    DCHECK(environment()->GetControlDependency() == node);

    StructuredGraphBuilder::Environment* continuation_env = environment();
    // Create environment for the deoptimization block, and build the block.
    StructuredGraphBuilder::Environment* deopt_env =
        CopyEnvironment(continuation_env);
    set_environment(deopt_env);

    NewNode(common()->LazyDeoptimization());

    // TODO(jarin) If ast_id.IsNone(), perhaps we should generate an empty
    // deopt block and make sure there is no patch entry for this (so
    // that the deoptimizer dies when trying to deoptimize here).

    Node* state_node = environment()->Checkpoint(ast_id);

    Node* deoptimize_node = NewNode(common()->Deoptimize(), state_node);

    UpdateControlDependencyToLeaveFunction(deoptimize_node);

    // Continue with the original environment.
    set_environment(continuation_env);

    NewNode(common()->Continuation());
  }
}


void AstGraphBuilder::BuildLazyBailoutWithPushedNode(Node* node,
                                                     BailoutId ast_id) {
  environment()->Push(node);
  BuildLazyBailout(node, ast_id);
  environment()->Pop();
}
}
}
}  // namespace v8::internal::compiler
