// Copyright 2015 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/interpreter/control-flow-builders.h"
#include "src/objects/objects-inl.h"

namespace v8 {
namespace internal {
namespace interpreter {


BreakableControlFlowBuilder::~BreakableControlFlowBuilder() {
  BindBreakTarget();
  DCHECK(break_labels_.empty() || break_labels_.is_bound());
  if (block_coverage_builder_ != nullptr) {
    block_coverage_builder_->IncrementBlockCounter(
        node_, SourceRangeKind::kContinuation);
  }
}

void BreakableControlFlowBuilder::BindBreakTarget() {
  break_labels_.Bind(builder());
}

void BreakableControlFlowBuilder::EmitJump(BytecodeLabels* sites) {
  builder()->Jump(sites->New());
}

void BreakableControlFlowBuilder::EmitJumpIfTrue(
    BytecodeArrayBuilder::ToBooleanMode mode, BytecodeLabels* sites) {
  builder()->JumpIfTrue(mode, sites->New());
}

void BreakableControlFlowBuilder::EmitJumpIfFalse(
    BytecodeArrayBuilder::ToBooleanMode mode, BytecodeLabels* sites) {
  builder()->JumpIfFalse(mode, sites->New());
}

void BreakableControlFlowBuilder::EmitJumpIfUndefined(BytecodeLabels* sites) {
  builder()->JumpIfUndefined(sites->New());
}

void BreakableControlFlowBuilder::EmitJumpIfNull(BytecodeLabels* sites) {
  builder()->JumpIfNull(sites->New());
}

LoopBuilder::~LoopBuilder() {
  DCHECK(continue_labels_.empty() || continue_labels_.is_bound());
}

void LoopBuilder::LoopHeader() {
  // Jumps from before the loop header into the loop violate ordering
  // requirements of bytecode basic blocks. The only entry into a loop
  // must be the loop header. Surely breaks is okay? Not if nested
  // and misplaced between the headers.
  DCHECK(break_labels_.empty() && continue_labels_.empty());
  builder()->Bind(&loop_header_);
}

void LoopBuilder::LoopBody() {
  if (block_coverage_builder_ != nullptr) {
    block_coverage_builder_->IncrementBlockCounter(block_coverage_body_slot_);
  }
}

void LoopBuilder::JumpToHeader(int loop_depth) {
  // Pass the proper loop nesting level to the backwards branch, to trigger
  // on-stack replacement when armed for the given loop nesting depth.
  int level = Min(loop_depth, AbstractCode::kMaxLoopNestingMarker - 1);
  // Loop must have closed form, i.e. all loop elements are within the loop,
  // the loop header precedes the body and next elements in the loop.
  builder()->JumpLoop(&loop_header_, level);
}

void LoopBuilder::BindContinueTarget() { continue_labels_.Bind(builder()); }

SwitchBuilder::~SwitchBuilder() {
#ifdef DEBUG
  for (auto site : case_sites_) {
    DCHECK(!site.has_referrer_jump() || site.is_bound());
  }
#endif
}

void SwitchBuilder::SetCaseTarget(int index, CaseClause* clause) {
  BytecodeLabel& site = case_sites_.at(index);
  builder()->Bind(&site);
  if (block_coverage_builder_) {
    block_coverage_builder_->IncrementBlockCounter(clause,
                                                   SourceRangeKind::kBody);
  }
}

TryCatchBuilder::~TryCatchBuilder() {
  if (block_coverage_builder_ != nullptr) {
    block_coverage_builder_->IncrementBlockCounter(
        statement_, SourceRangeKind::kContinuation);
  }
}

void TryCatchBuilder::BeginTry(Register context) {
  builder()->MarkTryBegin(handler_id_, context);
}


void TryCatchBuilder::EndTry() {
  builder()->MarkTryEnd(handler_id_);
  builder()->Jump(&exit_);
  builder()->MarkHandler(handler_id_, catch_prediction_);

  if (block_coverage_builder_ != nullptr) {
    block_coverage_builder_->IncrementBlockCounter(statement_,
                                                   SourceRangeKind::kCatch);
  }
}

void TryCatchBuilder::EndCatch() { builder()->Bind(&exit_); }

TryFinallyBuilder::~TryFinallyBuilder() {
  if (block_coverage_builder_ != nullptr) {
    block_coverage_builder_->IncrementBlockCounter(
        statement_, SourceRangeKind::kContinuation);
  }
}

void TryFinallyBuilder::BeginTry(Register context) {
  builder()->MarkTryBegin(handler_id_, context);
}


void TryFinallyBuilder::LeaveTry() {
  builder()->Jump(finalization_sites_.New());
}


void TryFinallyBuilder::EndTry() {
  builder()->MarkTryEnd(handler_id_);
}


void TryFinallyBuilder::BeginHandler() {
  builder()->Bind(&handler_);
  builder()->MarkHandler(handler_id_, catch_prediction_);
}

void TryFinallyBuilder::BeginFinally() {
  finalization_sites_.Bind(builder());

  if (block_coverage_builder_ != nullptr) {
    block_coverage_builder_->IncrementBlockCounter(statement_,
                                                   SourceRangeKind::kFinally);
  }
}

void TryFinallyBuilder::EndFinally() {
  // Nothing to be done here.
}

ConditionalControlFlowBuilder::~ConditionalControlFlowBuilder() {
  if (!else_labels_.is_bound()) else_labels_.Bind(builder());
  end_labels_.Bind(builder());

  DCHECK(end_labels_.empty() || end_labels_.is_bound());
  DCHECK(then_labels_.empty() || then_labels_.is_bound());
  DCHECK(else_labels_.empty() || else_labels_.is_bound());

  // IfStatement requires a continuation counter, Conditional does not (as it
  // can only contain expressions).
  if (block_coverage_builder_ != nullptr && node_->IsIfStatement()) {
    block_coverage_builder_->IncrementBlockCounter(
        node_, SourceRangeKind::kContinuation);
  }
}

void ConditionalControlFlowBuilder::JumpToEnd() {
  DCHECK(end_labels_.empty());  // May only be called once.
  builder()->Jump(end_labels_.New());
}

void ConditionalControlFlowBuilder::Then() {
  then_labels()->Bind(builder());
  if (block_coverage_builder_ != nullptr) {
    block_coverage_builder_->IncrementBlockCounter(block_coverage_then_slot_);
  }
}

void ConditionalControlFlowBuilder::Else() {
  else_labels()->Bind(builder());
  if (block_coverage_builder_ != nullptr) {
    block_coverage_builder_->IncrementBlockCounter(block_coverage_else_slot_);
  }
}

}  // namespace interpreter
}  // namespace internal
}  // namespace v8
