// 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());
  DCHECK(end_labels_.empty() || end_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() &&
         end_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, LoopBuilder* const parent_loop) {
  BindLoopEnd();
  if (parent_loop &&
      loop_header_.offset() == parent_loop->loop_header_.offset()) {
    // TurboFan can't cope with multiple loops that have the same loop header
    // bytecode offset. If we have an inner loop with the same header offset
    // than its parent loop, we do not create a JumpLoop bytecode. Instead, we
    // Jump to our parent's JumpToHeader which in turn can be a JumpLoop or, iff
    // they are a nested inner loop too, a Jump to its parent's JumpToHeader.
    parent_loop->JumpToLoopEnd();
  } else {
    // 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, source_position_);
  }
}

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

void LoopBuilder::BindLoopEnd() { end_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
