// Copyright 2012 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/full-codegen/full-codegen.h"

#include "src/ast/ast-numbering.h"
#include "src/ast/ast.h"
#include "src/ast/prettyprinter.h"
#include "src/ast/scopeinfo.h"
#include "src/ast/scopes.h"
#include "src/code-factory.h"
#include "src/codegen.h"
#include "src/compiler.h"
#include "src/debug/debug.h"
#include "src/debug/liveedit.h"
#include "src/frames-inl.h"
#include "src/isolate-inl.h"
#include "src/macro-assembler.h"
#include "src/snapshot/snapshot.h"
#include "src/tracing/trace-event.h"

namespace v8 {
namespace internal {

#define __ ACCESS_MASM(masm())

bool FullCodeGenerator::MakeCode(CompilationInfo* info) {
  Isolate* isolate = info->isolate();

  RuntimeCallTimerScope runtimeTimer(isolate,
                                     &RuntimeCallStats::CompileFullCode);
  TimerEventScope<TimerEventCompileFullCode> timer(info->isolate());
  TRACE_EVENT0("v8", "V8.CompileFullCode");

  Handle<Script> script = info->script();
  if (!script->IsUndefined(isolate) &&
      !script->source()->IsUndefined(isolate)) {
    int len = String::cast(script->source())->length();
    isolate->counters()->total_full_codegen_source_size()->Increment(len);
  }
  CodeGenerator::MakeCodePrologue(info, "full");
  const int kInitialBufferSize = 4 * KB;
  MacroAssembler masm(info->isolate(), NULL, kInitialBufferSize,
                      CodeObjectRequired::kYes);
  if (info->will_serialize()) masm.enable_serializer();

  LOG_CODE_EVENT(isolate,
                 CodeStartLinePosInfoRecordEvent(masm.positions_recorder()));

  FullCodeGenerator cgen(&masm, info);
  cgen.Generate();
  if (cgen.HasStackOverflow()) {
    DCHECK(!isolate->has_pending_exception());
    return false;
  }
  unsigned table_offset = cgen.EmitBackEdgeTable();

  Handle<Code> code = CodeGenerator::MakeCodeEpilogue(&masm, info);
  cgen.PopulateDeoptimizationData(code);
  cgen.PopulateTypeFeedbackInfo(code);
  cgen.PopulateHandlerTable(code);
  code->set_has_deoptimization_support(info->HasDeoptimizationSupport());
  code->set_has_reloc_info_for_serialization(info->will_serialize());
  code->set_allow_osr_at_loop_nesting_level(0);
  code->set_profiler_ticks(0);
  code->set_back_edge_table_offset(table_offset);
  CodeGenerator::PrintCode(code, info);
  info->SetCode(code);
  void* line_info = masm.positions_recorder()->DetachJITHandlerData();
  LOG_CODE_EVENT(isolate, CodeEndLinePosInfoRecordEvent(
                              AbstractCode::cast(*code), line_info));

#ifdef DEBUG
  // Check that no context-specific object has been embedded.
  code->VerifyEmbeddedObjects(Code::kNoContextSpecificPointers);
#endif  // DEBUG
  return true;
}


unsigned FullCodeGenerator::EmitBackEdgeTable() {
  // The back edge table consists of a length (in number of entries)
  // field, and then a sequence of entries.  Each entry is a pair of AST id
  // and code-relative pc offset.
  masm()->Align(kPointerSize);
  unsigned offset = masm()->pc_offset();
  unsigned length = back_edges_.length();
  __ dd(length);
  for (unsigned i = 0; i < length; ++i) {
    __ dd(back_edges_[i].id.ToInt());
    __ dd(back_edges_[i].pc);
    __ dd(back_edges_[i].loop_depth);
  }
  return offset;
}


void FullCodeGenerator::PopulateDeoptimizationData(Handle<Code> code) {
  // Fill in the deoptimization information.
  DCHECK(info_->HasDeoptimizationSupport() || bailout_entries_.is_empty());
  if (!info_->HasDeoptimizationSupport()) return;
  int length = bailout_entries_.length();
  Handle<DeoptimizationOutputData> data =
      DeoptimizationOutputData::New(isolate(), length, TENURED);
  for (int i = 0; i < length; i++) {
    data->SetAstId(i, bailout_entries_[i].id);
    data->SetPcAndState(i, Smi::FromInt(bailout_entries_[i].pc_and_state));
  }
  code->set_deoptimization_data(*data);
}


void FullCodeGenerator::PopulateTypeFeedbackInfo(Handle<Code> code) {
  Handle<TypeFeedbackInfo> info = isolate()->factory()->NewTypeFeedbackInfo();
  info->set_ic_total_count(ic_total_count_);
  DCHECK(!isolate()->heap()->InNewSpace(*info));
  code->set_type_feedback_info(*info);
}


void FullCodeGenerator::PopulateHandlerTable(Handle<Code> code) {
  int handler_table_size = static_cast<int>(handler_table_.size());
  Handle<HandlerTable> table =
      Handle<HandlerTable>::cast(isolate()->factory()->NewFixedArray(
          HandlerTable::LengthForRange(handler_table_size), TENURED));
  for (int i = 0; i < handler_table_size; ++i) {
    HandlerTable::CatchPrediction prediction =
        handler_table_[i].try_catch_depth > 0 ? HandlerTable::CAUGHT
                                              : HandlerTable::UNCAUGHT;
    table->SetRangeStart(i, handler_table_[i].range_start);
    table->SetRangeEnd(i, handler_table_[i].range_end);
    table->SetRangeHandler(i, handler_table_[i].handler_offset, prediction);
    table->SetRangeData(i, handler_table_[i].stack_depth);
  }
  code->set_handler_table(*table);
}


int FullCodeGenerator::NewHandlerTableEntry() {
  int index = static_cast<int>(handler_table_.size());
  HandlerTableEntry entry = {0, 0, 0, 0, 0};
  handler_table_.push_back(entry);
  return index;
}


bool FullCodeGenerator::MustCreateObjectLiteralWithRuntime(
    ObjectLiteral* expr) const {
  return masm()->serializer_enabled() ||
         !FastCloneShallowObjectStub::IsSupported(expr);
}


bool FullCodeGenerator::MustCreateArrayLiteralWithRuntime(
    ArrayLiteral* expr) const {
  return expr->depth() > 1 ||
         expr->values()->length() > JSArray::kInitialMaxFastElementArray;
}


void FullCodeGenerator::Initialize() {
  InitializeAstVisitor(info_->isolate());
  masm_->set_emit_debug_code(FLAG_debug_code);
  masm_->set_predictable_code_size(true);
}

void FullCodeGenerator::PrepareForBailout(Expression* node,
                                          BailoutState state) {
  PrepareForBailoutForId(node->id(), state);
}

void FullCodeGenerator::CallLoadIC(TypeFeedbackId id) {
  Handle<Code> ic = CodeFactory::LoadIC(isolate()).code();
  CallIC(ic, id);
}

void FullCodeGenerator::CallLoadGlobalIC(TypeofMode typeof_mode,
                                         TypeFeedbackId id) {
  Handle<Code> ic = CodeFactory::LoadGlobalIC(isolate(), typeof_mode).code();
  CallIC(ic, id);
}

void FullCodeGenerator::CallStoreIC(TypeFeedbackId id) {
  Handle<Code> ic = CodeFactory::StoreIC(isolate(), language_mode()).code();
  CallIC(ic, id);
}


void FullCodeGenerator::RecordJSReturnSite(Call* call) {
  // We record the offset of the function return so we can rebuild the frame
  // if the function was inlined, i.e., this is the return address in the
  // inlined function's frame.
  //
  // The bailout state is ignored.  We defensively set it to TOS_REGISTER, which
  // is the real state of the unoptimized code at the return site.
  PrepareForBailoutForId(call->ReturnId(), BailoutState::TOS_REGISTER);
#ifdef DEBUG
  // In debug builds, mark the return so we can verify that this function
  // was called.
  DCHECK(!call->return_is_recorded_);
  call->return_is_recorded_ = true;
#endif
}

void FullCodeGenerator::PrepareForBailoutForId(BailoutId id,
                                               BailoutState state) {
  // There's no need to prepare this code for bailouts from already optimized
  // code or code that can't be optimized.
  if (!info_->HasDeoptimizationSupport()) return;
  unsigned pc_and_state =
      BailoutStateField::encode(state) | PcField::encode(masm_->pc_offset());
  DCHECK(Smi::IsValid(pc_and_state));
#ifdef DEBUG
  for (int i = 0; i < bailout_entries_.length(); ++i) {
    DCHECK(bailout_entries_[i].id != id);
  }
#endif
  BailoutEntry entry = { id, pc_and_state };
  bailout_entries_.Add(entry, zone());
}


void FullCodeGenerator::RecordBackEdge(BailoutId ast_id) {
  // The pc offset does not need to be encoded and packed together with a state.
  DCHECK(masm_->pc_offset() > 0);
  DCHECK(loop_depth() > 0);
  uint8_t depth = Min(loop_depth(), Code::kMaxLoopNestingMarker);
  BackEdgeEntry entry =
      { ast_id, static_cast<unsigned>(masm_->pc_offset()), depth };
  back_edges_.Add(entry, zone());
}


bool FullCodeGenerator::ShouldInlineSmiCase(Token::Value op) {
  // Inline smi case inside loops, but not division and modulo which
  // are too complicated and take up too much space.
  if (op == Token::DIV ||op == Token::MOD) return false;
  if (FLAG_always_inline_smi_code) return true;
  return loop_depth_ > 0;
}


void FullCodeGenerator::EffectContext::Plug(Variable* var) const {
  DCHECK(var->IsStackAllocated() || var->IsContextSlot());
}


void FullCodeGenerator::AccumulatorValueContext::Plug(Variable* var) const {
  DCHECK(var->IsStackAllocated() || var->IsContextSlot());
  codegen()->GetVar(result_register(), var);
}


void FullCodeGenerator::TestContext::Plug(Variable* var) const {
  DCHECK(var->IsStackAllocated() || var->IsContextSlot());
  // For simplicity we always test the accumulator register.
  codegen()->GetVar(result_register(), var);
  codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL);
  codegen()->DoTest(this);
}


void FullCodeGenerator::EffectContext::Plug(Register reg) const {
}


void FullCodeGenerator::AccumulatorValueContext::Plug(Register reg) const {
  __ Move(result_register(), reg);
}


void FullCodeGenerator::StackValueContext::Plug(Register reg) const {
  codegen()->PushOperand(reg);
}


void FullCodeGenerator::TestContext::Plug(Register reg) const {
  // For simplicity we always test the accumulator register.
  __ Move(result_register(), reg);
  codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL);
  codegen()->DoTest(this);
}


void FullCodeGenerator::EffectContext::Plug(bool flag) const {}

void FullCodeGenerator::EffectContext::DropAndPlug(int count,
                                                   Register reg) const {
  DCHECK(count > 0);
  codegen()->DropOperands(count);
}

void FullCodeGenerator::AccumulatorValueContext::DropAndPlug(
    int count, Register reg) const {
  DCHECK(count > 0);
  codegen()->DropOperands(count);
  __ Move(result_register(), reg);
}

void FullCodeGenerator::TestContext::DropAndPlug(int count,
                                                 Register reg) const {
  DCHECK(count > 0);
  // For simplicity we always test the accumulator register.
  codegen()->DropOperands(count);
  __ Move(result_register(), reg);
  codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL);
  codegen()->DoTest(this);
}

void FullCodeGenerator::EffectContext::PlugTOS() const {
  codegen()->DropOperands(1);
}


void FullCodeGenerator::AccumulatorValueContext::PlugTOS() const {
  codegen()->PopOperand(result_register());
}


void FullCodeGenerator::StackValueContext::PlugTOS() const {
}


void FullCodeGenerator::TestContext::PlugTOS() const {
  // For simplicity we always test the accumulator register.
  codegen()->PopOperand(result_register());
  codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL);
  codegen()->DoTest(this);
}


void FullCodeGenerator::EffectContext::PrepareTest(
    Label* materialize_true,
    Label* materialize_false,
    Label** if_true,
    Label** if_false,
    Label** fall_through) const {
  // In an effect context, the true and the false case branch to the
  // same label.
  *if_true = *if_false = *fall_through = materialize_true;
}


void FullCodeGenerator::AccumulatorValueContext::PrepareTest(
    Label* materialize_true,
    Label* materialize_false,
    Label** if_true,
    Label** if_false,
    Label** fall_through) const {
  *if_true = *fall_through = materialize_true;
  *if_false = materialize_false;
}


void FullCodeGenerator::StackValueContext::PrepareTest(
    Label* materialize_true,
    Label* materialize_false,
    Label** if_true,
    Label** if_false,
    Label** fall_through) const {
  *if_true = *fall_through = materialize_true;
  *if_false = materialize_false;
}


void FullCodeGenerator::TestContext::PrepareTest(
    Label* materialize_true,
    Label* materialize_false,
    Label** if_true,
    Label** if_false,
    Label** fall_through) const {
  *if_true = true_label_;
  *if_false = false_label_;
  *fall_through = fall_through_;
}


void FullCodeGenerator::DoTest(const TestContext* context) {
  DoTest(context->condition(),
         context->true_label(),
         context->false_label(),
         context->fall_through());
}


void FullCodeGenerator::VisitDeclarations(
    ZoneList<Declaration*>* declarations) {
  ZoneList<Handle<Object> >* saved_globals = globals_;
  ZoneList<Handle<Object> > inner_globals(10, zone());
  globals_ = &inner_globals;

  AstVisitor::VisitDeclarations(declarations);

  if (!globals_->is_empty()) {
    // Invoke the platform-dependent code generator to do the actual
    // declaration of the global functions and variables.
    Handle<FixedArray> array =
       isolate()->factory()->NewFixedArray(globals_->length(), TENURED);
    for (int i = 0; i < globals_->length(); ++i)
      array->set(i, *globals_->at(i));
    DeclareGlobals(array);
  }

  globals_ = saved_globals;
}


void FullCodeGenerator::VisitImportDeclaration(ImportDeclaration* declaration) {
  VariableProxy* proxy = declaration->proxy();
  Variable* variable = proxy->var();
  switch (variable->location()) {
    case VariableLocation::GLOBAL:
    case VariableLocation::UNALLOCATED:
      // TODO(rossberg)
      break;

    case VariableLocation::CONTEXT: {
      Comment cmnt(masm_, "[ ImportDeclaration");
      EmitDebugCheckDeclarationContext(variable);
      // TODO(rossberg)
      break;
    }

    case VariableLocation::PARAMETER:
    case VariableLocation::LOCAL:
    case VariableLocation::LOOKUP:
      UNREACHABLE();
  }
}


void FullCodeGenerator::VisitExportDeclaration(ExportDeclaration* declaration) {
  // TODO(rossberg)
}


void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
  Comment cmnt(masm_, "[ VariableProxy");
  EmitVariableLoad(expr);
}


void FullCodeGenerator::VisitSloppyBlockFunctionStatement(
    SloppyBlockFunctionStatement* declaration) {
  Visit(declaration->statement());
}


int FullCodeGenerator::DeclareGlobalsFlags() {
  return info_->GetDeclareGlobalsFlags();
}

void FullCodeGenerator::PushOperand(Handle<Object> handle) {
  OperandStackDepthIncrement(1);
  __ Push(handle);
}

void FullCodeGenerator::PushOperand(Smi* smi) {
  OperandStackDepthIncrement(1);
  __ Push(smi);
}

void FullCodeGenerator::PushOperand(Register reg) {
  OperandStackDepthIncrement(1);
  __ Push(reg);
}

void FullCodeGenerator::PopOperand(Register reg) {
  OperandStackDepthDecrement(1);
  __ Pop(reg);
}

void FullCodeGenerator::DropOperands(int count) {
  OperandStackDepthDecrement(count);
  __ Drop(count);
}

void FullCodeGenerator::CallRuntimeWithOperands(Runtime::FunctionId id) {
  OperandStackDepthDecrement(Runtime::FunctionForId(id)->nargs);
  __ CallRuntime(id);
}

void FullCodeGenerator::OperandStackDepthIncrement(int count) {
  DCHECK_IMPLIES(!HasStackOverflow(), operand_stack_depth_ >= 0);
  DCHECK_GE(count, 0);
  operand_stack_depth_ += count;
}

void FullCodeGenerator::OperandStackDepthDecrement(int count) {
  DCHECK_IMPLIES(!HasStackOverflow(), operand_stack_depth_ >= count);
  DCHECK_GE(count, 0);
  operand_stack_depth_ -= count;
}

void FullCodeGenerator::EmitSubString(CallRuntime* expr) {
  // Load the arguments on the stack and call the stub.
  SubStringStub stub(isolate());
  ZoneList<Expression*>* args = expr->arguments();
  DCHECK(args->length() == 3);
  VisitForStackValue(args->at(0));
  VisitForStackValue(args->at(1));
  VisitForStackValue(args->at(2));
  __ CallStub(&stub);
  OperandStackDepthDecrement(3);
  context()->Plug(result_register());
}


void FullCodeGenerator::EmitRegExpExec(CallRuntime* expr) {
  // Load the arguments on the stack and call the stub.
  RegExpExecStub stub(isolate());
  ZoneList<Expression*>* args = expr->arguments();
  DCHECK(args->length() == 4);
  VisitForStackValue(args->at(0));
  VisitForStackValue(args->at(1));
  VisitForStackValue(args->at(2));
  VisitForStackValue(args->at(3));
  __ CallStub(&stub);
  OperandStackDepthDecrement(4);
  context()->Plug(result_register());
}


void FullCodeGenerator::EmitMathPow(CallRuntime* expr) {
  // Load the arguments on the stack and call the runtime function.
  MathPowStub stub(isolate(), MathPowStub::ON_STACK);
  ZoneList<Expression*>* args = expr->arguments();
  DCHECK(args->length() == 2);
  VisitForStackValue(args->at(0));
  VisitForStackValue(args->at(1));
  __ CallStub(&stub);
  OperandStackDepthDecrement(2);
  context()->Plug(result_register());
}


void FullCodeGenerator::EmitIntrinsicAsStubCall(CallRuntime* expr,
                                                const Callable& callable) {
  ZoneList<Expression*>* args = expr->arguments();
  int param_count = callable.descriptor().GetRegisterParameterCount();
  DCHECK_EQ(args->length(), param_count);

  if (param_count > 0) {
    int last = param_count - 1;
    // Put all but last arguments on stack.
    for (int i = 0; i < last; i++) {
      VisitForStackValue(args->at(i));
    }
    // The last argument goes to the accumulator.
    VisitForAccumulatorValue(args->at(last));

    // Move the arguments to the registers, as required by the stub.
    __ Move(callable.descriptor().GetRegisterParameter(last),
            result_register());
    for (int i = last; i-- > 0;) {
      PopOperand(callable.descriptor().GetRegisterParameter(i));
    }
  }
  __ Call(callable.code(), RelocInfo::CODE_TARGET);

  // Reload the context register after the call as i.e. TurboFan code stubs
  // won't preserve the context register.
  LoadFromFrameField(StandardFrameConstants::kContextOffset,
                     context_register());
  context()->Plug(result_register());
}

void FullCodeGenerator::EmitNewObject(CallRuntime* expr) {
  EmitIntrinsicAsStubCall(expr, CodeFactory::FastNewObject(isolate()));
}

void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) {
  EmitIntrinsicAsStubCall(expr, CodeFactory::NumberToString(isolate()));
}


void FullCodeGenerator::EmitToString(CallRuntime* expr) {
  EmitIntrinsicAsStubCall(expr, CodeFactory::ToString(isolate()));
}


void FullCodeGenerator::EmitToName(CallRuntime* expr) {
  EmitIntrinsicAsStubCall(expr, CodeFactory::ToName(isolate()));
}


void FullCodeGenerator::EmitToLength(CallRuntime* expr) {
  EmitIntrinsicAsStubCall(expr, CodeFactory::ToLength(isolate()));
}

void FullCodeGenerator::EmitToInteger(CallRuntime* expr) {
  EmitIntrinsicAsStubCall(expr, CodeFactory::ToInteger(isolate()));
}

void FullCodeGenerator::EmitToNumber(CallRuntime* expr) {
  EmitIntrinsicAsStubCall(expr, CodeFactory::ToNumber(isolate()));
}


void FullCodeGenerator::EmitToObject(CallRuntime* expr) {
  EmitIntrinsicAsStubCall(expr, CodeFactory::ToObject(isolate()));
}


void FullCodeGenerator::EmitRegExpConstructResult(CallRuntime* expr) {
  EmitIntrinsicAsStubCall(expr, CodeFactory::RegExpConstructResult(isolate()));
}

void FullCodeGenerator::EmitHasProperty() {
  Callable callable = CodeFactory::HasProperty(isolate());
  PopOperand(callable.descriptor().GetRegisterParameter(1));
  PopOperand(callable.descriptor().GetRegisterParameter(0));
  __ Call(callable.code(), RelocInfo::CODE_TARGET);
  RestoreContext();
}

void RecordStatementPosition(MacroAssembler* masm, int pos) {
  if (pos == RelocInfo::kNoPosition) return;
  masm->positions_recorder()->RecordStatementPosition(pos);
}

void RecordPosition(MacroAssembler* masm, int pos) {
  if (pos == RelocInfo::kNoPosition) return;
  masm->positions_recorder()->RecordPosition(pos);
}


void FullCodeGenerator::SetFunctionPosition(FunctionLiteral* fun) {
  RecordPosition(masm_, fun->start_position());
}


void FullCodeGenerator::SetReturnPosition(FunctionLiteral* fun) {
  // For default constructors, start position equals end position, and there
  // is no source code besides the class literal.
  int pos = std::max(fun->start_position(), fun->end_position() - 1);
  RecordStatementPosition(masm_, pos);
  if (info_->is_debug()) {
    // Always emit a debug break slot before a return.
    DebugCodegen::GenerateSlot(masm_, RelocInfo::DEBUG_BREAK_SLOT_AT_RETURN);
  }
}


void FullCodeGenerator::SetStatementPosition(
    Statement* stmt, FullCodeGenerator::InsertBreak insert_break) {
  if (stmt->position() == RelocInfo::kNoPosition) return;
  RecordStatementPosition(masm_, stmt->position());
  if (insert_break == INSERT_BREAK && info_->is_debug() &&
      !stmt->IsDebuggerStatement()) {
    DebugCodegen::GenerateSlot(masm_, RelocInfo::DEBUG_BREAK_SLOT_AT_POSITION);
  }
}

void FullCodeGenerator::SetExpressionPosition(Expression* expr) {
  if (expr->position() == RelocInfo::kNoPosition) return;
  RecordPosition(masm_, expr->position());
}


void FullCodeGenerator::SetExpressionAsStatementPosition(Expression* expr) {
  if (expr->position() == RelocInfo::kNoPosition) return;
  RecordStatementPosition(masm_, expr->position());
  if (info_->is_debug()) {
    DebugCodegen::GenerateSlot(masm_, RelocInfo::DEBUG_BREAK_SLOT_AT_POSITION);
  }
}

void FullCodeGenerator::SetCallPosition(Expression* expr,
                                        TailCallMode tail_call_mode) {
  if (expr->position() == RelocInfo::kNoPosition) return;
  RecordPosition(masm_, expr->position());
  if (info_->is_debug()) {
    RelocInfo::Mode mode = (tail_call_mode == TailCallMode::kAllow)
                               ? RelocInfo::DEBUG_BREAK_SLOT_AT_TAIL_CALL
                               : RelocInfo::DEBUG_BREAK_SLOT_AT_CALL;
    // Always emit a debug break slot before a call.
    DebugCodegen::GenerateSlot(masm_, mode);
  }
}


void FullCodeGenerator::VisitSuperPropertyReference(
    SuperPropertyReference* super) {
  __ CallRuntime(Runtime::kThrowUnsupportedSuperError);
  // Even though this expression doesn't produce a value, we need to simulate
  // plugging of the value context to ensure stack depth tracking is in sync.
  if (context()->IsStackValue()) OperandStackDepthIncrement(1);
}


void FullCodeGenerator::VisitSuperCallReference(SuperCallReference* super) {
  // Handled by VisitCall
  UNREACHABLE();
}


void FullCodeGenerator::EmitDebugBreakInOptimizedCode(CallRuntime* expr) {
  context()->Plug(handle(Smi::FromInt(0), isolate()));
}


void FullCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
  switch (expr->op()) {
    case Token::COMMA:
      return VisitComma(expr);
    case Token::OR:
    case Token::AND:
      return VisitLogicalExpression(expr);
    default:
      return VisitArithmeticExpression(expr);
  }
}


void FullCodeGenerator::VisitInDuplicateContext(Expression* expr) {
  if (context()->IsEffect()) {
    VisitForEffect(expr);
  } else if (context()->IsAccumulatorValue()) {
    VisitForAccumulatorValue(expr);
  } else if (context()->IsStackValue()) {
    VisitForStackValue(expr);
  } else if (context()->IsTest()) {
    const TestContext* test = TestContext::cast(context());
    VisitForControl(expr, test->true_label(), test->false_label(),
                    test->fall_through());
  }
}


void FullCodeGenerator::VisitComma(BinaryOperation* expr) {
  Comment cmnt(masm_, "[ Comma");
  VisitForEffect(expr->left());
  VisitInDuplicateContext(expr->right());
}


void FullCodeGenerator::VisitLogicalExpression(BinaryOperation* expr) {
  bool is_logical_and = expr->op() == Token::AND;
  Comment cmnt(masm_, is_logical_and ? "[ Logical AND" :  "[ Logical OR");
  Expression* left = expr->left();
  Expression* right = expr->right();
  BailoutId right_id = expr->RightId();
  Label done;

  if (context()->IsTest()) {
    Label eval_right;
    const TestContext* test = TestContext::cast(context());
    if (is_logical_and) {
      VisitForControl(left, &eval_right, test->false_label(), &eval_right);
    } else {
      VisitForControl(left, test->true_label(), &eval_right, &eval_right);
    }
    PrepareForBailoutForId(right_id, BailoutState::NO_REGISTERS);
    __ bind(&eval_right);

  } else if (context()->IsAccumulatorValue()) {
    VisitForAccumulatorValue(left);
    // We want the value in the accumulator for the test, and on the stack in
    // case we need it.
    __ Push(result_register());
    Label discard, restore;
    if (is_logical_and) {
      DoTest(left, &discard, &restore, &restore);
    } else {
      DoTest(left, &restore, &discard, &restore);
    }
    __ bind(&restore);
    __ Pop(result_register());
    __ jmp(&done);
    __ bind(&discard);
    __ Drop(1);
    PrepareForBailoutForId(right_id, BailoutState::NO_REGISTERS);

  } else if (context()->IsStackValue()) {
    VisitForAccumulatorValue(left);
    // We want the value in the accumulator for the test, and on the stack in
    // case we need it.
    __ Push(result_register());
    Label discard;
    if (is_logical_and) {
      DoTest(left, &discard, &done, &discard);
    } else {
      DoTest(left, &done, &discard, &discard);
    }
    __ bind(&discard);
    __ Drop(1);
    PrepareForBailoutForId(right_id, BailoutState::NO_REGISTERS);

  } else {
    DCHECK(context()->IsEffect());
    Label eval_right;
    if (is_logical_and) {
      VisitForControl(left, &eval_right, &done, &eval_right);
    } else {
      VisitForControl(left, &done, &eval_right, &eval_right);
    }
    PrepareForBailoutForId(right_id, BailoutState::NO_REGISTERS);
    __ bind(&eval_right);
  }

  VisitInDuplicateContext(right);
  __ bind(&done);
}


void FullCodeGenerator::VisitArithmeticExpression(BinaryOperation* expr) {
  Token::Value op = expr->op();
  Comment cmnt(masm_, "[ ArithmeticExpression");
  Expression* left = expr->left();
  Expression* right = expr->right();

  VisitForStackValue(left);
  VisitForAccumulatorValue(right);

  SetExpressionPosition(expr);
  if (ShouldInlineSmiCase(op)) {
    EmitInlineSmiBinaryOp(expr, op, left, right);
  } else {
    EmitBinaryOp(expr, op);
  }
}

void FullCodeGenerator::VisitProperty(Property* expr) {
  Comment cmnt(masm_, "[ Property");
  SetExpressionPosition(expr);

  Expression* key = expr->key();

  if (key->IsPropertyName()) {
    if (!expr->IsSuperAccess()) {
      VisitForAccumulatorValue(expr->obj());
      __ Move(LoadDescriptor::ReceiverRegister(), result_register());
      EmitNamedPropertyLoad(expr);
    } else {
      VisitForStackValue(expr->obj()->AsSuperPropertyReference()->this_var());
      VisitForStackValue(
          expr->obj()->AsSuperPropertyReference()->home_object());
      EmitNamedSuperPropertyLoad(expr);
    }
  } else {
    if (!expr->IsSuperAccess()) {
      VisitForStackValue(expr->obj());
      VisitForAccumulatorValue(expr->key());
      __ Move(LoadDescriptor::NameRegister(), result_register());
      PopOperand(LoadDescriptor::ReceiverRegister());
      EmitKeyedPropertyLoad(expr);
    } else {
      VisitForStackValue(expr->obj()->AsSuperPropertyReference()->this_var());
      VisitForStackValue(
          expr->obj()->AsSuperPropertyReference()->home_object());
      VisitForStackValue(expr->key());
      EmitKeyedSuperPropertyLoad(expr);
    }
  }
  PrepareForBailoutForId(expr->LoadId(), BailoutState::TOS_REGISTER);
  context()->Plug(result_register());
}

void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
  VariableProxy* proxy = expr->AsVariableProxy();
  DCHECK(!context()->IsEffect());
  DCHECK(!context()->IsTest());

  if (proxy != NULL && (proxy->var()->IsUnallocatedOrGlobalSlot() ||
                        proxy->var()->IsLookupSlot())) {
    EmitVariableLoad(proxy, INSIDE_TYPEOF);
    PrepareForBailout(proxy, BailoutState::TOS_REGISTER);
  } else {
    // This expression cannot throw a reference error at the top level.
    VisitInDuplicateContext(expr);
  }
}


void FullCodeGenerator::VisitBlock(Block* stmt) {
  Comment cmnt(masm_, "[ Block");
  NestedBlock nested_block(this, stmt);

  {
    EnterBlockScopeIfNeeded block_scope_state(
        this, stmt->scope(), stmt->EntryId(), stmt->DeclsId(), stmt->ExitId());
    VisitStatements(stmt->statements());
    __ bind(nested_block.break_label());
  }
}


void FullCodeGenerator::VisitDoExpression(DoExpression* expr) {
  Comment cmnt(masm_, "[ Do Expression");
  SetExpressionPosition(expr);
  VisitBlock(expr->block());
  EmitVariableLoad(expr->result());
}


void FullCodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) {
  Comment cmnt(masm_, "[ ExpressionStatement");
  SetStatementPosition(stmt);
  VisitForEffect(stmt->expression());
}


void FullCodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) {
  Comment cmnt(masm_, "[ EmptyStatement");
}


void FullCodeGenerator::VisitIfStatement(IfStatement* stmt) {
  Comment cmnt(masm_, "[ IfStatement");
  SetStatementPosition(stmt);
  Label then_part, else_part, done;

  if (stmt->HasElseStatement()) {
    VisitForControl(stmt->condition(), &then_part, &else_part, &then_part);
    PrepareForBailoutForId(stmt->ThenId(), BailoutState::NO_REGISTERS);
    __ bind(&then_part);
    Visit(stmt->then_statement());
    __ jmp(&done);

    PrepareForBailoutForId(stmt->ElseId(), BailoutState::NO_REGISTERS);
    __ bind(&else_part);
    Visit(stmt->else_statement());
  } else {
    VisitForControl(stmt->condition(), &then_part, &done, &then_part);
    PrepareForBailoutForId(stmt->ThenId(), BailoutState::NO_REGISTERS);
    __ bind(&then_part);
    Visit(stmt->then_statement());

    PrepareForBailoutForId(stmt->ElseId(), BailoutState::NO_REGISTERS);
  }
  __ bind(&done);
  PrepareForBailoutForId(stmt->IfId(), BailoutState::NO_REGISTERS);
}

void FullCodeGenerator::EmitContinue(Statement* target) {
  NestedStatement* current = nesting_stack_;
  int context_length = 0;
  // When continuing, we clobber the unpredictable value in the accumulator
  // with one that's safe for GC.  If we hit an exit from the try block of
  // try...finally on our way out, we will unconditionally preserve the
  // accumulator on the stack.
  ClearAccumulator();
  while (!current->IsContinueTarget(target)) {
    if (current->IsTryFinally()) {
      Comment cmnt(masm(), "[ Deferred continue through finally");
      current->Exit(&context_length);
      DCHECK_EQ(-1, context_length);
      current->AsTryFinally()->deferred_commands()->RecordContinue(target);
      return;
    }
    current = current->Exit(&context_length);
  }
  int stack_depth = current->GetStackDepthAtTarget();
  int stack_drop = operand_stack_depth_ - stack_depth;
  DCHECK_GE(stack_drop, 0);
  __ Drop(stack_drop);
  if (context_length > 0) {
    while (context_length > 0) {
      LoadContextField(context_register(), Context::PREVIOUS_INDEX);
      --context_length;
    }
    StoreToFrameField(StandardFrameConstants::kContextOffset,
                      context_register());
  }

  __ jmp(current->AsIteration()->continue_label());
}

void FullCodeGenerator::VisitContinueStatement(ContinueStatement* stmt) {
  Comment cmnt(masm_, "[ ContinueStatement");
  SetStatementPosition(stmt);
  EmitContinue(stmt->target());
}

void FullCodeGenerator::EmitBreak(Statement* target) {
  NestedStatement* current = nesting_stack_;
  int context_length = 0;
  // When breaking, we clobber the unpredictable value in the accumulator
  // with one that's safe for GC.  If we hit an exit from the try block of
  // try...finally on our way out, we will unconditionally preserve the
  // accumulator on the stack.
  ClearAccumulator();
  while (!current->IsBreakTarget(target)) {
    if (current->IsTryFinally()) {
      Comment cmnt(masm(), "[ Deferred break through finally");
      current->Exit(&context_length);
      DCHECK_EQ(-1, context_length);
      current->AsTryFinally()->deferred_commands()->RecordBreak(target);
      return;
    }
    current = current->Exit(&context_length);
  }
  int stack_depth = current->GetStackDepthAtTarget();
  int stack_drop = operand_stack_depth_ - stack_depth;
  DCHECK_GE(stack_drop, 0);
  __ Drop(stack_drop);
  if (context_length > 0) {
    while (context_length > 0) {
      LoadContextField(context_register(), Context::PREVIOUS_INDEX);
      --context_length;
    }
    StoreToFrameField(StandardFrameConstants::kContextOffset,
                      context_register());
  }

  __ jmp(current->AsBreakable()->break_label());
}

void FullCodeGenerator::VisitBreakStatement(BreakStatement* stmt) {
  Comment cmnt(masm_, "[ BreakStatement");
  SetStatementPosition(stmt);
  EmitBreak(stmt->target());
}

void FullCodeGenerator::EmitUnwindAndReturn() {
  NestedStatement* current = nesting_stack_;
  int context_length = 0;
  while (current != NULL) {
    if (current->IsTryFinally()) {
      Comment cmnt(masm(), "[ Deferred return through finally");
      current->Exit(&context_length);
      DCHECK_EQ(-1, context_length);
      current->AsTryFinally()->deferred_commands()->RecordReturn();
      return;
    }
    current = current->Exit(&context_length);
  }
  EmitReturnSequence();
}

void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
                                       bool pretenure) {
  // If we're running with the --always-opt or the --prepare-always-opt
  // flag, we need to use the runtime function so that the new function
  // we are creating here gets a chance to have its code optimized and
  // doesn't just get a copy of the existing unoptimized code.
  if (!FLAG_always_opt && !FLAG_prepare_always_opt && !pretenure &&
      scope()->is_function_scope()) {
    FastNewClosureStub stub(isolate(), info->language_mode(), info->kind());
    __ Move(stub.GetCallInterfaceDescriptor().GetRegisterParameter(0), info);
    __ CallStub(&stub);
  } else {
    __ Push(info);
    __ CallRuntime(pretenure ? Runtime::kNewClosure_Tenured
                             : Runtime::kNewClosure);
  }
  context()->Plug(result_register());
}

void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
  SetExpressionPosition(prop);
  Literal* key = prop->key()->AsLiteral();
  DCHECK(!key->value()->IsSmi());
  DCHECK(!prop->IsSuperAccess());

  __ Move(LoadDescriptor::NameRegister(), key->value());
  __ Move(LoadDescriptor::SlotRegister(),
          SmiFromSlot(prop->PropertyFeedbackSlot()));
  CallLoadIC();
}

void FullCodeGenerator::EmitNamedSuperPropertyLoad(Property* prop) {
  // Stack: receiver, home_object
  SetExpressionPosition(prop);
  Literal* key = prop->key()->AsLiteral();
  DCHECK(!key->value()->IsSmi());
  DCHECK(prop->IsSuperAccess());

  PushOperand(key->value());
  CallRuntimeWithOperands(Runtime::kLoadFromSuper);
}

void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
  SetExpressionPosition(prop);
  Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).code();
  __ Move(LoadDescriptor::SlotRegister(),
          SmiFromSlot(prop->PropertyFeedbackSlot()));
  CallIC(ic);
}

void FullCodeGenerator::EmitKeyedSuperPropertyLoad(Property* prop) {
  // Stack: receiver, home_object, key.
  SetExpressionPosition(prop);
  CallRuntimeWithOperands(Runtime::kLoadKeyedFromSuper);
}

void FullCodeGenerator::EmitPropertyKey(ObjectLiteralProperty* property,
                                        BailoutId bailout_id) {
  VisitForStackValue(property->key());
  CallRuntimeWithOperands(Runtime::kToName);
  PrepareForBailoutForId(bailout_id, BailoutState::NO_REGISTERS);
  PushOperand(result_register());
}

void FullCodeGenerator::EmitLoadStoreICSlot(FeedbackVectorSlot slot) {
  DCHECK(!slot.IsInvalid());
  __ Move(VectorStoreICTrampolineDescriptor::SlotRegister(), SmiFromSlot(slot));
}

void FullCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
  Comment cmnt(masm_, "[ ReturnStatement");
  SetStatementPosition(stmt);
  Expression* expr = stmt->expression();
  VisitForAccumulatorValue(expr);
  EmitUnwindAndReturn();
}


void FullCodeGenerator::VisitWithStatement(WithStatement* stmt) {
  Comment cmnt(masm_, "[ WithStatement");
  SetStatementPosition(stmt);

  VisitForAccumulatorValue(stmt->expression());
  Callable callable = CodeFactory::ToObject(isolate());
  __ Move(callable.descriptor().GetRegisterParameter(0), result_register());
  __ Call(callable.code(), RelocInfo::CODE_TARGET);
  PrepareForBailoutForId(stmt->ToObjectId(), BailoutState::NO_REGISTERS);
  PushOperand(result_register());
  PushFunctionArgumentForContextAllocation();
  CallRuntimeWithOperands(Runtime::kPushWithContext);
  StoreToFrameField(StandardFrameConstants::kContextOffset, context_register());
  PrepareForBailoutForId(stmt->EntryId(), BailoutState::NO_REGISTERS);

  Scope* saved_scope = scope();
  scope_ = stmt->scope();
  { WithOrCatch body(this);
    Visit(stmt->statement());
  }
  scope_ = saved_scope;

  // Pop context.
  LoadContextField(context_register(), Context::PREVIOUS_INDEX);
  // Update local stack frame context field.
  StoreToFrameField(StandardFrameConstants::kContextOffset, context_register());
}


void FullCodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) {
  Comment cmnt(masm_, "[ DoWhileStatement");
  // Do not insert break location as we do that below.
  SetStatementPosition(stmt, SKIP_BREAK);

  Label body, book_keeping;

  Iteration loop_statement(this, stmt);
  increment_loop_depth();

  __ bind(&body);
  Visit(stmt->body());

  // Record the position of the do while condition and make sure it is
  // possible to break on the condition.
  __ bind(loop_statement.continue_label());
  PrepareForBailoutForId(stmt->ContinueId(), BailoutState::NO_REGISTERS);

  // Here is the actual 'while' keyword.
  SetExpressionAsStatementPosition(stmt->cond());
  VisitForControl(stmt->cond(),
                  &book_keeping,
                  loop_statement.break_label(),
                  &book_keeping);

  // Check stack before looping.
  PrepareForBailoutForId(stmt->BackEdgeId(), BailoutState::NO_REGISTERS);
  __ bind(&book_keeping);
  EmitBackEdgeBookkeeping(stmt, &body);
  __ jmp(&body);

  PrepareForBailoutForId(stmt->ExitId(), BailoutState::NO_REGISTERS);
  __ bind(loop_statement.break_label());
  decrement_loop_depth();
}


void FullCodeGenerator::VisitWhileStatement(WhileStatement* stmt) {
  Comment cmnt(masm_, "[ WhileStatement");
  Label loop, body;

  Iteration loop_statement(this, stmt);
  increment_loop_depth();

  __ bind(&loop);

  SetExpressionAsStatementPosition(stmt->cond());
  VisitForControl(stmt->cond(),
                  &body,
                  loop_statement.break_label(),
                  &body);

  PrepareForBailoutForId(stmt->BodyId(), BailoutState::NO_REGISTERS);
  __ bind(&body);
  Visit(stmt->body());

  __ bind(loop_statement.continue_label());

  // Check stack before looping.
  EmitBackEdgeBookkeeping(stmt, &loop);
  __ jmp(&loop);

  PrepareForBailoutForId(stmt->ExitId(), BailoutState::NO_REGISTERS);
  __ bind(loop_statement.break_label());
  decrement_loop_depth();
}


void FullCodeGenerator::VisitForStatement(ForStatement* stmt) {
  Comment cmnt(masm_, "[ ForStatement");
  // Do not insert break location as we do it below.
  SetStatementPosition(stmt, SKIP_BREAK);

  Label test, body;

  Iteration loop_statement(this, stmt);

  if (stmt->init() != NULL) {
    Visit(stmt->init());
  }

  increment_loop_depth();
  // Emit the test at the bottom of the loop (even if empty).
  __ jmp(&test);

  PrepareForBailoutForId(stmt->BodyId(), BailoutState::NO_REGISTERS);
  __ bind(&body);
  Visit(stmt->body());

  PrepareForBailoutForId(stmt->ContinueId(), BailoutState::NO_REGISTERS);
  __ bind(loop_statement.continue_label());
  if (stmt->next() != NULL) {
    SetStatementPosition(stmt->next());
    Visit(stmt->next());
  }

  // Check stack before looping.
  EmitBackEdgeBookkeeping(stmt, &body);

  __ bind(&test);
  if (stmt->cond() != NULL) {
    SetExpressionAsStatementPosition(stmt->cond());
    VisitForControl(stmt->cond(),
                    &body,
                    loop_statement.break_label(),
                    loop_statement.break_label());
  } else {
    __ jmp(&body);
  }

  PrepareForBailoutForId(stmt->ExitId(), BailoutState::NO_REGISTERS);
  __ bind(loop_statement.break_label());
  decrement_loop_depth();
}


void FullCodeGenerator::VisitForOfStatement(ForOfStatement* stmt) {
  Comment cmnt(masm_, "[ ForOfStatement");

  Iteration loop_statement(this, stmt);
  increment_loop_depth();

  // var iterator = iterable[Symbol.iterator]();
  SetExpressionAsStatementPosition(stmt->assign_iterator());
  VisitForEffect(stmt->assign_iterator());

  // Loop entry.
  __ bind(loop_statement.continue_label());

  // result = iterator.next()
  SetExpressionAsStatementPosition(stmt->next_result());
  VisitForEffect(stmt->next_result());

  // if (result.done) break;
  Label result_not_done;
  VisitForControl(stmt->result_done(), loop_statement.break_label(),
                  &result_not_done, &result_not_done);
  __ bind(&result_not_done);

  // each = result.value
  VisitForEffect(stmt->assign_each());

  // Generate code for the body of the loop.
  Visit(stmt->body());

  // Check stack before looping.
  PrepareForBailoutForId(stmt->BackEdgeId(), BailoutState::NO_REGISTERS);
  EmitBackEdgeBookkeeping(stmt, loop_statement.continue_label());
  __ jmp(loop_statement.continue_label());

  // Exit and decrement the loop depth.
  PrepareForBailoutForId(stmt->ExitId(), BailoutState::NO_REGISTERS);
  __ bind(loop_statement.break_label());
  decrement_loop_depth();
}

void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) {
  LoadFromFrameField(JavaScriptFrameConstants::kFunctionOffset,
                     result_register());
  context()->Plug(result_register());
}

void FullCodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) {
  Comment cmnt(masm_, "[ TryCatchStatement");
  SetStatementPosition(stmt, SKIP_BREAK);

  // The try block adds a handler to the exception handler chain before
  // entering, and removes it again when exiting normally.  If an exception
  // is thrown during execution of the try block, the handler is consumed
  // and control is passed to the catch block with the exception in the
  // result register.

  Label try_entry, handler_entry, exit;
  __ jmp(&try_entry);
  __ bind(&handler_entry);
  if (stmt->clear_pending_message()) ClearPendingMessage();

  // Exception handler code, the exception is in the result register.
  // Extend the context before executing the catch block.
  { Comment cmnt(masm_, "[ Extend catch context");
    PushOperand(stmt->variable()->name());
    PushOperand(result_register());
    PushFunctionArgumentForContextAllocation();
    CallRuntimeWithOperands(Runtime::kPushCatchContext);
    StoreToFrameField(StandardFrameConstants::kContextOffset,
                      context_register());
  }

  Scope* saved_scope = scope();
  scope_ = stmt->scope();
  DCHECK(scope_->declarations()->is_empty());
  { WithOrCatch catch_body(this);
    Visit(stmt->catch_block());
  }
  // Restore the context.
  LoadContextField(context_register(), Context::PREVIOUS_INDEX);
  StoreToFrameField(StandardFrameConstants::kContextOffset, context_register());
  scope_ = saved_scope;
  __ jmp(&exit);

  // Try block code. Sets up the exception handler chain.
  __ bind(&try_entry);

  try_catch_depth_++;
  int handler_index = NewHandlerTableEntry();
  EnterTryBlock(handler_index, &handler_entry);
  {
    Comment cmnt_try(masm(), "[ Try block");
    Visit(stmt->try_block());
  }
  ExitTryBlock(handler_index);
  try_catch_depth_--;
  __ bind(&exit);
}


void FullCodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
  Comment cmnt(masm_, "[ TryFinallyStatement");
  SetStatementPosition(stmt, SKIP_BREAK);

  // Try finally is compiled by setting up a try-handler on the stack while
  // executing the try body, and removing it again afterwards.
  //
  // The try-finally construct can enter the finally block in three ways:
  // 1. By exiting the try-block normally. This exits the try block,
  //    pushes the continuation token and falls through to the finally
  //    block.
  // 2. By exiting the try-block with a function-local control flow transfer
  //    (break/continue/return). The site of the, e.g., break exits the
  //    try block, pushes the continuation token and jumps to the
  //    finally block. After the finally block executes, the execution
  //    continues based on the continuation token to a block that
  //    continues with the control flow transfer.
  // 3. By exiting the try-block with a thrown exception. In the handler,
  //    we push the exception and continuation token and jump to the
  //    finally block (which will again dispatch based on the token once
  //    it is finished).

  Label try_entry, handler_entry, finally_entry;
  DeferredCommands deferred(this, &finally_entry);

  // Jump to try-handler setup and try-block code.
  __ jmp(&try_entry);
  __ bind(&handler_entry);

  // Exception handler code.  This code is only executed when an exception
  // is thrown.  Record the continuation and jump to the finally block.
  {
    Comment cmnt_handler(masm(), "[ Finally handler");
    deferred.RecordThrow();
  }

  // Set up try handler.
  __ bind(&try_entry);
  int handler_index = NewHandlerTableEntry();
  EnterTryBlock(handler_index, &handler_entry);
  {
    Comment cmnt_try(masm(), "[ Try block");
    TryFinally try_body(this, &deferred);
    Visit(stmt->try_block());
  }
  ExitTryBlock(handler_index);
  // Execute the finally block on the way out.  Clobber the unpredictable
  // value in the result register with one that's safe for GC because the
  // finally block will unconditionally preserve the result register on the
  // stack.
  ClearAccumulator();
  deferred.EmitFallThrough();
  // Fall through to the finally block.

  // Finally block implementation.
  __ bind(&finally_entry);
  {
    Comment cmnt_finally(masm(), "[ Finally block");
    OperandStackDepthIncrement(2);  // Token and accumulator are on stack.
    EnterFinallyBlock();
    Visit(stmt->finally_block());
    ExitFinallyBlock();
    OperandStackDepthDecrement(2);  // Token and accumulator were on stack.
  }

  {
    Comment cmnt_deferred(masm(), "[ Post-finally dispatch");
    deferred.EmitCommands();  // Return to the calling code.
  }
}


void FullCodeGenerator::VisitDebuggerStatement(DebuggerStatement* stmt) {
  Comment cmnt(masm_, "[ DebuggerStatement");
  SetStatementPosition(stmt);

  __ DebugBreak();
  // Ignore the return value.

  PrepareForBailoutForId(stmt->DebugBreakId(), BailoutState::NO_REGISTERS);
}


void FullCodeGenerator::VisitCaseClause(CaseClause* clause) {
  UNREACHABLE();
}


void FullCodeGenerator::VisitConditional(Conditional* expr) {
  Comment cmnt(masm_, "[ Conditional");
  Label true_case, false_case, done;
  VisitForControl(expr->condition(), &true_case, &false_case, &true_case);

  int original_stack_depth = operand_stack_depth_;
  PrepareForBailoutForId(expr->ThenId(), BailoutState::NO_REGISTERS);
  __ bind(&true_case);
  SetExpressionPosition(expr->then_expression());
  if (context()->IsTest()) {
    const TestContext* for_test = TestContext::cast(context());
    VisitForControl(expr->then_expression(),
                    for_test->true_label(),
                    for_test->false_label(),
                    NULL);
  } else {
    VisitInDuplicateContext(expr->then_expression());
    __ jmp(&done);
  }

  operand_stack_depth_ = original_stack_depth;
  PrepareForBailoutForId(expr->ElseId(), BailoutState::NO_REGISTERS);
  __ bind(&false_case);
  SetExpressionPosition(expr->else_expression());
  VisitInDuplicateContext(expr->else_expression());
  // If control flow falls through Visit, merge it with true case here.
  if (!context()->IsTest()) {
    __ bind(&done);
  }
}


void FullCodeGenerator::VisitLiteral(Literal* expr) {
  Comment cmnt(masm_, "[ Literal");
  context()->Plug(expr->value());
}


void FullCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
  Comment cmnt(masm_, "[ FunctionLiteral");

  // Build the function boilerplate and instantiate it.
  Handle<SharedFunctionInfo> function_info =
      Compiler::GetSharedFunctionInfo(expr, script(), info_);
  if (function_info.is_null()) {
    SetStackOverflow();
    return;
  }
  EmitNewClosure(function_info, expr->pretenure());
}


void FullCodeGenerator::VisitClassLiteral(ClassLiteral* lit) {
  Comment cmnt(masm_, "[ ClassLiteral");

  {
    NestedClassLiteral nested_class_literal(this, lit);
    EnterBlockScopeIfNeeded block_scope_state(
        this, lit->scope(), lit->EntryId(), lit->DeclsId(), lit->ExitId());

    if (lit->extends() != NULL) {
      VisitForStackValue(lit->extends());
    } else {
      PushOperand(isolate()->factory()->the_hole_value());
    }

    VisitForStackValue(lit->constructor());

    PushOperand(Smi::FromInt(lit->start_position()));
    PushOperand(Smi::FromInt(lit->end_position()));

    CallRuntimeWithOperands(Runtime::kDefineClass);
    PrepareForBailoutForId(lit->CreateLiteralId(), BailoutState::TOS_REGISTER);
    PushOperand(result_register());

    // Load the "prototype" from the constructor.
    __ Move(LoadDescriptor::ReceiverRegister(), result_register());
    __ LoadRoot(LoadDescriptor::NameRegister(),
                Heap::kprototype_stringRootIndex);
    __ Move(LoadDescriptor::SlotRegister(), SmiFromSlot(lit->PrototypeSlot()));
    CallLoadIC();
    PrepareForBailoutForId(lit->PrototypeId(), BailoutState::TOS_REGISTER);
    PushOperand(result_register());

    EmitClassDefineProperties(lit);
    DropOperands(1);

    // Set the constructor to have fast properties.
    CallRuntimeWithOperands(Runtime::kToFastProperties);

    if (lit->class_variable_proxy() != nullptr) {
      EmitVariableAssignment(lit->class_variable_proxy()->var(), Token::INIT,
                             lit->ProxySlot());
    }
  }

  context()->Plug(result_register());
}

void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
  Comment cmnt(masm_, "[ RegExpLiteral");
  Callable callable = CodeFactory::FastCloneRegExp(isolate());
  CallInterfaceDescriptor descriptor = callable.descriptor();
  LoadFromFrameField(JavaScriptFrameConstants::kFunctionOffset,
                     descriptor.GetRegisterParameter(0));
  __ Move(descriptor.GetRegisterParameter(1),
          Smi::FromInt(expr->literal_index()));
  __ Move(descriptor.GetRegisterParameter(2), expr->pattern());
  __ Move(descriptor.GetRegisterParameter(3), Smi::FromInt(expr->flags()));
  __ Call(callable.code(), RelocInfo::CODE_TARGET);
  context()->Plug(result_register());
}

void FullCodeGenerator::VisitNativeFunctionLiteral(
    NativeFunctionLiteral* expr) {
  Comment cmnt(masm_, "[ NativeFunctionLiteral");
  Handle<SharedFunctionInfo> shared =
      Compiler::GetSharedFunctionInfoForNative(expr->extension(), expr->name());
  EmitNewClosure(shared, false);
}


void FullCodeGenerator::VisitThrow(Throw* expr) {
  Comment cmnt(masm_, "[ Throw");
  VisitForStackValue(expr->exception());
  SetExpressionPosition(expr);
  CallRuntimeWithOperands(Runtime::kThrow);
  // Never returns here.

  // Even though this expression doesn't produce a value, we need to simulate
  // plugging of the value context to ensure stack depth tracking is in sync.
  if (context()->IsStackValue()) OperandStackDepthIncrement(1);
}


void FullCodeGenerator::EnterTryBlock(int handler_index, Label* handler) {
  HandlerTableEntry* entry = &handler_table_[handler_index];
  entry->range_start = masm()->pc_offset();
  entry->handler_offset = handler->pos();
  entry->try_catch_depth = try_catch_depth_;
  entry->stack_depth = operand_stack_depth_;

  // We are using the operand stack depth, check for accuracy.
  EmitOperandStackDepthCheck();

  // Push context onto operand stack.
  STATIC_ASSERT(TryBlockConstant::kElementCount == 1);
  PushOperand(context_register());
}


void FullCodeGenerator::ExitTryBlock(int handler_index) {
  HandlerTableEntry* entry = &handler_table_[handler_index];
  entry->range_end = masm()->pc_offset();

  // Drop context from operand stack.
  DropOperands(TryBlockConstant::kElementCount);
}


void FullCodeGenerator::VisitCall(Call* expr) {
#ifdef DEBUG
  // We want to verify that RecordJSReturnSite gets called on all paths
  // through this function.  Avoid early returns.
  expr->return_is_recorded_ = false;
#endif

  Comment cmnt(masm_, (expr->tail_call_mode() == TailCallMode::kAllow)
                          ? "[ TailCall"
                          : "[ Call");
  Expression* callee = expr->expression();
  Call::CallType call_type = expr->GetCallType(isolate());

  switch (call_type) {
    case Call::POSSIBLY_EVAL_CALL:
      EmitPossiblyEvalCall(expr);
      break;
    case Call::GLOBAL_CALL:
      EmitCallWithLoadIC(expr);
      break;
    case Call::LOOKUP_SLOT_CALL:
      // Call to a lookup slot (dynamically introduced variable).
      PushCalleeAndWithBaseObject(expr);
      EmitCall(expr);
      break;
    case Call::NAMED_PROPERTY_CALL: {
      Property* property = callee->AsProperty();
      VisitForStackValue(property->obj());
      EmitCallWithLoadIC(expr);
      break;
    }
    case Call::KEYED_PROPERTY_CALL: {
      Property* property = callee->AsProperty();
      VisitForStackValue(property->obj());
      EmitKeyedCallWithLoadIC(expr, property->key());
      break;
    }
    case Call::NAMED_SUPER_PROPERTY_CALL:
      EmitSuperCallWithLoadIC(expr);
      break;
    case Call::KEYED_SUPER_PROPERTY_CALL:
      EmitKeyedSuperCallWithLoadIC(expr);
      break;
    case Call::SUPER_CALL:
      EmitSuperConstructorCall(expr);
      break;
    case Call::OTHER_CALL:
      // Call to an arbitrary expression not handled specially above.
      VisitForStackValue(callee);
      OperandStackDepthIncrement(1);
      __ PushRoot(Heap::kUndefinedValueRootIndex);
      // Emit function call.
      EmitCall(expr);
      break;
  }

#ifdef DEBUG
  // RecordJSReturnSite should have been called.
  DCHECK(expr->return_is_recorded_);
#endif
}

void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
  ZoneList<Expression*>* args = expr->arguments();
  int arg_count = args->length();

  if (expr->is_jsruntime()) {
    Comment cmnt(masm_, "[ CallRuntime");
    EmitLoadJSRuntimeFunction(expr);

    // Push the arguments ("left-to-right").
    for (int i = 0; i < arg_count; i++) {
      VisitForStackValue(args->at(i));
    }

    PrepareForBailoutForId(expr->CallId(), BailoutState::NO_REGISTERS);
    EmitCallJSRuntimeFunction(expr);
    context()->DropAndPlug(1, result_register());

  } else {
    const Runtime::Function* function = expr->function();
    switch (function->function_id) {
#define CALL_INTRINSIC_GENERATOR(Name)     \
  case Runtime::kInline##Name: {           \
    Comment cmnt(masm_, "[ Inline" #Name); \
    return Emit##Name(expr);               \
  }
      FOR_EACH_FULL_CODE_INTRINSIC(CALL_INTRINSIC_GENERATOR)
#undef CALL_INTRINSIC_GENERATOR
      default: {
        Comment cmnt(masm_, "[ CallRuntime for unhandled intrinsic");
        // Push the arguments ("left-to-right").
        for (int i = 0; i < arg_count; i++) {
          VisitForStackValue(args->at(i));
        }

        // Call the C runtime function.
        PrepareForBailoutForId(expr->CallId(), BailoutState::NO_REGISTERS);
        __ CallRuntime(expr->function(), arg_count);
        OperandStackDepthDecrement(arg_count);
        context()->Plug(result_register());
      }
    }
  }
}

void FullCodeGenerator::VisitSpread(Spread* expr) { UNREACHABLE(); }


void FullCodeGenerator::VisitEmptyParentheses(EmptyParentheses* expr) {
  UNREACHABLE();
}


void FullCodeGenerator::VisitRewritableExpression(RewritableExpression* expr) {
  Visit(expr->expression());
}

FullCodeGenerator::NestedStatement* FullCodeGenerator::TryFinally::Exit(
    int* context_length) {
  // The macros used here must preserve the result register.

  // Calculate how many operands to drop to get down to handler block.
  int stack_drop = codegen_->operand_stack_depth_ - GetStackDepthAtTarget();
  DCHECK_GE(stack_drop, 0);

  // Because the handler block contains the context of the finally
  // code, we can restore it directly from there for the finally code
  // rather than iteratively unwinding contexts via their previous
  // links.
  if (*context_length > 0) {
    __ Drop(stack_drop);  // Down to the handler block.
    // Restore the context to its dedicated register and the stack.
    STATIC_ASSERT(TryBlockConstant::kElementCount == 1);
    __ Pop(codegen_->context_register());
    codegen_->StoreToFrameField(StandardFrameConstants::kContextOffset,
                                codegen_->context_register());
  } else {
    // Down to the handler block and also drop context.
    __ Drop(stack_drop + TryBlockConstant::kElementCount);
  }

  // The caller will ignore outputs.
  *context_length = -1;
  return previous_;
}

void FullCodeGenerator::DeferredCommands::RecordBreak(Statement* target) {
  TokenId token = dispenser_.GetBreakContinueToken();
  commands_.push_back({kBreak, token, target});
  EmitJumpToFinally(token);
}

void FullCodeGenerator::DeferredCommands::RecordContinue(Statement* target) {
  TokenId token = dispenser_.GetBreakContinueToken();
  commands_.push_back({kContinue, token, target});
  EmitJumpToFinally(token);
}

void FullCodeGenerator::DeferredCommands::RecordReturn() {
  if (return_token_ == TokenDispenserForFinally::kInvalidToken) {
    return_token_ = TokenDispenserForFinally::kReturnToken;
    commands_.push_back({kReturn, return_token_, nullptr});
  }
  EmitJumpToFinally(return_token_);
}

void FullCodeGenerator::DeferredCommands::RecordThrow() {
  if (throw_token_ == TokenDispenserForFinally::kInvalidToken) {
    throw_token_ = TokenDispenserForFinally::kThrowToken;
    commands_.push_back({kThrow, throw_token_, nullptr});
  }
  EmitJumpToFinally(throw_token_);
}

void FullCodeGenerator::DeferredCommands::EmitFallThrough() {
  __ Push(Smi::FromInt(TokenDispenserForFinally::kFallThroughToken));
  __ Push(result_register());
}

void FullCodeGenerator::DeferredCommands::EmitJumpToFinally(TokenId token) {
  __ Push(Smi::FromInt(token));
  __ Push(result_register());
  __ jmp(finally_entry_);
}

bool FullCodeGenerator::TryLiteralCompare(CompareOperation* expr) {
  Expression* sub_expr;
  Handle<String> check;
  if (expr->IsLiteralCompareTypeof(&sub_expr, &check)) {
    SetExpressionPosition(expr);
    EmitLiteralCompareTypeof(expr, sub_expr, check);
    return true;
  }

  if (expr->IsLiteralCompareUndefined(&sub_expr)) {
    SetExpressionPosition(expr);
    EmitLiteralCompareNil(expr, sub_expr, kUndefinedValue);
    return true;
  }

  if (expr->IsLiteralCompareNull(&sub_expr)) {
    SetExpressionPosition(expr);
    EmitLiteralCompareNil(expr, sub_expr, kNullValue);
    return true;
  }

  return false;
}


void BackEdgeTable::Patch(Isolate* isolate, Code* unoptimized) {
  DisallowHeapAllocation no_gc;
  Code* patch = isolate->builtins()->builtin(Builtins::kOnStackReplacement);

  // Increment loop nesting level by one and iterate over the back edge table
  // to find the matching loops to patch the interrupt
  // call to an unconditional call to the replacement code.
  int loop_nesting_level = unoptimized->allow_osr_at_loop_nesting_level() + 1;
  if (loop_nesting_level > Code::kMaxLoopNestingMarker) return;

  BackEdgeTable back_edges(unoptimized, &no_gc);
  for (uint32_t i = 0; i < back_edges.length(); i++) {
    if (static_cast<int>(back_edges.loop_depth(i)) == loop_nesting_level) {
      DCHECK_EQ(INTERRUPT, GetBackEdgeState(isolate,
                                            unoptimized,
                                            back_edges.pc(i)));
      PatchAt(unoptimized, back_edges.pc(i), ON_STACK_REPLACEMENT, patch);
    }
  }

  unoptimized->set_allow_osr_at_loop_nesting_level(loop_nesting_level);
  DCHECK(Verify(isolate, unoptimized));
}


void BackEdgeTable::Revert(Isolate* isolate, Code* unoptimized) {
  DisallowHeapAllocation no_gc;
  Code* patch = isolate->builtins()->builtin(Builtins::kInterruptCheck);

  // Iterate over the back edge table and revert the patched interrupt calls.
  int loop_nesting_level = unoptimized->allow_osr_at_loop_nesting_level();

  BackEdgeTable back_edges(unoptimized, &no_gc);
  for (uint32_t i = 0; i < back_edges.length(); i++) {
    if (static_cast<int>(back_edges.loop_depth(i)) <= loop_nesting_level) {
      DCHECK_NE(INTERRUPT, GetBackEdgeState(isolate,
                                            unoptimized,
                                            back_edges.pc(i)));
      PatchAt(unoptimized, back_edges.pc(i), INTERRUPT, patch);
    }
  }

  unoptimized->set_allow_osr_at_loop_nesting_level(0);
  // Assert that none of the back edges are patched anymore.
  DCHECK(Verify(isolate, unoptimized));
}


#ifdef DEBUG
bool BackEdgeTable::Verify(Isolate* isolate, Code* unoptimized) {
  DisallowHeapAllocation no_gc;
  int loop_nesting_level = unoptimized->allow_osr_at_loop_nesting_level();
  BackEdgeTable back_edges(unoptimized, &no_gc);
  for (uint32_t i = 0; i < back_edges.length(); i++) {
    uint32_t loop_depth = back_edges.loop_depth(i);
    CHECK_LE(static_cast<int>(loop_depth), Code::kMaxLoopNestingMarker);
    // Assert that all back edges for shallower loops (and only those)
    // have already been patched.
    CHECK_EQ((static_cast<int>(loop_depth) <= loop_nesting_level),
             GetBackEdgeState(isolate,
                              unoptimized,
                              back_edges.pc(i)) != INTERRUPT);
  }
  return true;
}
#endif  // DEBUG


FullCodeGenerator::EnterBlockScopeIfNeeded::EnterBlockScopeIfNeeded(
    FullCodeGenerator* codegen, Scope* scope, BailoutId entry_id,
    BailoutId declarations_id, BailoutId exit_id)
    : codegen_(codegen), exit_id_(exit_id) {
  saved_scope_ = codegen_->scope();

  if (scope == NULL) {
    codegen_->PrepareForBailoutForId(entry_id, BailoutState::NO_REGISTERS);
    needs_block_context_ = false;
  } else {
    needs_block_context_ = scope->NeedsContext();
    codegen_->scope_ = scope;
    {
      if (needs_block_context_) {
        Comment cmnt(masm(), "[ Extend block context");
        codegen_->PushOperand(scope->GetScopeInfo(codegen->isolate()));
        codegen_->PushFunctionArgumentForContextAllocation();
        codegen_->CallRuntimeWithOperands(Runtime::kPushBlockContext);

        // Replace the context stored in the frame.
        codegen_->StoreToFrameField(StandardFrameConstants::kContextOffset,
                                    codegen_->context_register());
      }
      CHECK_EQ(0, scope->num_stack_slots());
      codegen_->PrepareForBailoutForId(entry_id, BailoutState::NO_REGISTERS);
    }
    {
      Comment cmnt(masm(), "[ Declarations");
      codegen_->VisitDeclarations(scope->declarations());
      codegen_->PrepareForBailoutForId(declarations_id,
                                       BailoutState::NO_REGISTERS);
    }
  }
}


FullCodeGenerator::EnterBlockScopeIfNeeded::~EnterBlockScopeIfNeeded() {
  if (needs_block_context_) {
    codegen_->LoadContextField(codegen_->context_register(),
                               Context::PREVIOUS_INDEX);
    // Update local stack frame context field.
    codegen_->StoreToFrameField(StandardFrameConstants::kContextOffset,
                                codegen_->context_register());
  }
  codegen_->PrepareForBailoutForId(exit_id_, BailoutState::NO_REGISTERS);
  codegen_->scope_ = saved_scope_;
}


bool FullCodeGenerator::NeedsHoleCheckForLoad(VariableProxy* proxy) {
  Variable* var = proxy->var();

  if (!var->binding_needs_init()) {
    return false;
  }

  // var->scope() may be NULL when the proxy is located in eval code and
  // refers to a potential outside binding. Currently those bindings are
  // always looked up dynamically, i.e. in that case
  //     var->location() == LOOKUP.
  // always holds.
  DCHECK(var->scope() != NULL);
  DCHECK(var->location() == VariableLocation::PARAMETER ||
         var->location() == VariableLocation::LOCAL ||
         var->location() == VariableLocation::CONTEXT);

  // Check if the binding really needs an initialization check. The check
  // can be skipped in the following situation: we have a LET or CONST
  // binding in harmony mode, both the Variable and the VariableProxy have
  // the same declaration scope (i.e. they are both in global code, in the
  // same function or in the same eval code), the VariableProxy is in
  // the source physically located after the initializer of the variable,
  // and that the initializer cannot be skipped due to a nonlinear scope.
  //
  // We cannot skip any initialization checks for CONST in non-harmony
  // mode because const variables may be declared but never initialized:
  //   if (false) { const x; }; var y = x;
  //
  // The condition on the declaration scopes is a conservative check for
  // nested functions that access a binding and are called before the
  // binding is initialized:
  //   function() { f(); let x = 1; function f() { x = 2; } }
  //
  // The check cannot be skipped on non-linear scopes, namely switch
  // scopes, to ensure tests are done in cases like the following:
  //   switch (1) { case 0: let x = 2; case 1: f(x); }
  // The scope of the variable needs to be checked, in case the use is
  // in a sub-block which may be linear.
  if (var->scope()->DeclarationScope() != scope()->DeclarationScope()) {
    return true;
  }

  if (var->is_this()) {
    DCHECK(literal() != nullptr &&
           (literal()->kind() & kSubclassConstructor) != 0);
    // TODO(littledan): implement 'this' hole check elimination.
    return true;
  }

  // Check that we always have valid source position.
  DCHECK(var->initializer_position() != RelocInfo::kNoPosition);
  DCHECK(proxy->position() != RelocInfo::kNoPosition);

  return var->scope()->is_nonlinear() ||
         var->initializer_position() >= proxy->position();
}


#undef __


}  // namespace internal
}  // namespace v8
