// Copyright 2017 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/objects/debug-objects.h"

#include "src/base/platform/mutex.h"
#include "src/debug/debug-evaluate.h"
#include "src/handles/handles-inl.h"
#include "src/objects/call-site-info-inl.h"
#include "src/objects/debug-objects-inl.h"
#include "src/utils/ostreams.h"

namespace v8 {
namespace internal {

bool DebugInfo::IsEmpty() const {
  return flags(kRelaxedLoad) == kNone && debugger_hints() == 0;
}

bool DebugInfo::HasBreakInfo() const {
  return flags(kRelaxedLoad).contains(kHasBreakInfo);
}

DebugInfo::ExecutionMode DebugInfo::DebugExecutionMode() const {
  return flags(kRelaxedLoad).contains(kDebugExecutionMode) ? kSideEffects
                                                           : kBreakpoints;
}

void DebugInfo::SetDebugExecutionMode(ExecutionMode value) {
  set_flags(value == kSideEffects
                ? flags(kRelaxedLoad).with(kDebugExecutionMode)
                : flags(kRelaxedLoad).without(kDebugExecutionMode),
            kRelaxedStore);
}

void DebugInfo::ClearBreakInfo(Isolate* isolate) {
  if (HasInstrumentedBytecodeArray()) {
    // If the function is currently running on the stack, we need to update the
    // bytecode pointers on the stack so they point to the original
    // BytecodeArray before releasing that BytecodeArray from this DebugInfo.
    // Otherwise, it could be flushed and cause problems on resume. See v8:9067.
    {
      RedirectActiveFunctions redirect_visitor(
          isolate, shared(),
          RedirectActiveFunctions::Mode::kUseOriginalBytecode);
      redirect_visitor.VisitThread(isolate, isolate->thread_local_top());
      isolate->thread_manager()->IterateArchivedThreads(&redirect_visitor);
    }

    SharedFunctionInfo::UninstallDebugBytecode(shared(), isolate);
  }
  set_break_points(ReadOnlyRoots(isolate).empty_fixed_array());

  Flags new_flags =
      flags(kRelaxedLoad)
          .without({kHasBreakInfo, kPreparedForDebugExecution, kBreakAtEntry,
                    kCanBreakAtEntry, kDebugExecutionMode});
  set_flags(new_flags, kRelaxedStore);
}

void DebugInfo::SetBreakAtEntry() {
  DCHECK(CanBreakAtEntry());
  set_flags(flags(kRelaxedLoad) | kBreakAtEntry, kRelaxedStore);
}

void DebugInfo::ClearBreakAtEntry() {
  DCHECK(CanBreakAtEntry());
  set_flags(flags(kRelaxedLoad).without(kBreakAtEntry), kRelaxedStore);
}

bool DebugInfo::BreakAtEntry() const {
  return flags(kRelaxedLoad).contains(kBreakAtEntry);
}

bool DebugInfo::CanBreakAtEntry() const {
  return flags(kRelaxedLoad).contains(kCanBreakAtEntry);
}

// Check if there is a break point at this source position.
bool DebugInfo::HasBreakPoint(Isolate* isolate, int source_position) {
  DCHECK(HasBreakInfo());
  // Get the break point info object for this code offset.
  Tagged<Object> break_point_info = GetBreakPointInfo(isolate, source_position);

  // If there is no break point info object or no break points in the break
  // point info object there is no break point at this code offset.
  if (IsUndefined(break_point_info)) return false;
  return Cast<BreakPointInfo>(break_point_info)->GetBreakPointCount(isolate) >
         0;
}

// Get the break point info object for this source position.
Tagged<Object> DebugInfo::GetBreakPointInfo(Isolate* isolate,
                                            int source_position) {
  DCHECK(HasBreakInfo());
  const uint32_t break_points_len = break_points()->ulength().value();
  for (uint32_t i = 0; i < break_points_len; i++) {
    if (!IsUndefined(break_points()->get(i))) {
      Tagged<BreakPointInfo> break_point_info =
          Cast<BreakPointInfo>(break_points()->get(i));
      if (break_point_info->source_position() == source_position) {
        return break_point_info;
      }
    }
  }
  return ReadOnlyRoots(isolate).undefined_value();
}

bool DebugInfo::ClearBreakPoint(Isolate* isolate,
                                DirectHandle<DebugInfo> debug_info,
                                DirectHandle<BreakPoint> break_point) {
  DCHECK(debug_info->HasBreakInfo());
  const uint32_t break_points_len =
      debug_info->break_points()->ulength().value();
  for (uint32_t i = 0; i < break_points_len; i++) {
    if (IsUndefined(debug_info->break_points()->get(i))) continue;
    DirectHandle<BreakPointInfo> break_point_info(
        Cast<BreakPointInfo>(debug_info->break_points()->get(i)), isolate);
    if (BreakPointInfo::HasBreakPoint(isolate, break_point_info, break_point)) {
      BreakPointInfo::ClearBreakPoint(isolate, break_point_info, break_point);
      return true;
    }
  }
  return false;
}

void DebugInfo::SetBreakPoint(Isolate* isolate,
                              DirectHandle<DebugInfo> debug_info,
                              int source_position,
                              DirectHandle<BreakPoint> break_point) {
  DCHECK(debug_info->HasBreakInfo());
  DirectHandle<Object> break_point_info(
      debug_info->GetBreakPointInfo(isolate, source_position), isolate);
  if (!IsUndefined(*break_point_info)) {
    BreakPointInfo::SetBreakPoint(
        isolate, Cast<BreakPointInfo>(break_point_info), break_point);
    return;
  }

  // Adding a new break point for a code offset which did not have any
  // break points before. Try to find a free slot.
  std::optional<uint32_t> index;
  const uint32_t break_points_len =
      debug_info->break_points()->ulength().value();
  for (uint32_t i = 0; i < break_points_len; i++) {
    if (IsUndefined(debug_info->break_points()->get(i))) {
      index = i;
      break;
    }
  }
  if (!index) {
    // No free slot - extend break point info array.
    DirectHandle<FixedArray> old_break_points(debug_info->break_points(),
                                              isolate);
    DirectHandle<FixedArray> new_break_points =
        isolate->factory()->NewFixedArray(
            break_points_len + DebugInfo::kEstimatedNofBreakPointsInFunction);

    debug_info->set_break_points(*new_break_points);
    for (uint32_t i = 0; i < break_points_len; i++) {
      new_break_points->set(i, old_break_points->get(i));
    }
    index = break_points_len;
  }
  DCHECK(index.has_value());

  // Allocate new BreakPointInfo object and set the break point.
  DirectHandle<BreakPointInfo> new_break_point_info =
      isolate->factory()->NewBreakPointInfo(source_position);
  BreakPointInfo::SetBreakPoint(isolate, new_break_point_info, break_point);
  debug_info->break_points()->set(*index, *new_break_point_info);
}

// Get the break point objects for a source position.
DirectHandle<Object> DebugInfo::GetBreakPoints(Isolate* isolate,
                                               int source_position) {
  DCHECK(HasBreakInfo());
  Tagged<Object> break_point_info = GetBreakPointInfo(isolate, source_position);
  if (IsUndefined(break_point_info)) {
    return isolate->factory()->undefined_value();
  }
  return DirectHandle<Object>(
      Cast<BreakPointInfo>(break_point_info)->break_points(), isolate);
}

// Get the total number of break points.
uint32_t DebugInfo::GetBreakPointCount(Isolate* isolate) {
  DCHECK(HasBreakInfo());
  uint32_t count = 0;
  uint32_t break_points_len = break_points()->ulength().value();
  for (uint32_t i = 0; i < break_points_len; i++) {
    if (!IsUndefined(break_points()->get(i))) {
      Tagged<BreakPointInfo> break_point_info =
          Cast<BreakPointInfo>(break_points()->get(i));
      count += break_point_info->GetBreakPointCount(isolate);
    }
  }
  return count;
}

DirectHandle<Object> DebugInfo::FindBreakPointInfo(
    Isolate* isolate, DirectHandle<DebugInfo> debug_info,
    DirectHandle<BreakPoint> break_point) {
  DCHECK(debug_info->HasBreakInfo());
  const uint32_t break_points_len =
      debug_info->break_points()->ulength().value();
  for (uint32_t i = 0; i < break_points_len; i++) {
    if (!IsUndefined(debug_info->break_points()->get(i))) {
      DirectHandle<BreakPointInfo> break_point_info(
          Cast<BreakPointInfo>(debug_info->break_points()->get(i)), isolate);
      if (BreakPointInfo::HasBreakPoint(isolate, break_point_info,
                                        break_point)) {
        return break_point_info;
      }
    }
  }
  return isolate->factory()->undefined_value();
}

bool DebugInfo::HasCoverageInfo() const {
  return flags(kRelaxedLoad).contains(kHasCoverageInfo);
}

void DebugInfo::ClearCoverageInfo(Isolate* isolate) {
  if (HasCoverageInfo()) {
    set_coverage_info(ReadOnlyRoots(isolate).undefined_value());

    Flags new_flags = flags(kRelaxedLoad).without(kHasCoverageInfo);
    set_flags(new_flags, kRelaxedStore);
  }
}

DebugInfo::SideEffectState DebugInfo::GetSideEffectState(Isolate* isolate) {
  if (side_effect_state() == kNotComputed) {
    SideEffectState has_no_side_effect =
        DebugEvaluate::FunctionGetSideEffectState(
            isolate, direct_handle(shared(), isolate));
    set_side_effect_state(has_no_side_effect);
  }
  return static_cast<SideEffectState>(side_effect_state());
}

namespace {
bool IsEqual(Tagged<BreakPoint> break_point1, Tagged<BreakPoint> break_point2) {
  return break_point1->id() == break_point2->id();
}
}  // namespace

// Remove the specified break point object.
void BreakPointInfo::ClearBreakPoint(
    Isolate* isolate, DirectHandle<BreakPointInfo> break_point_info,
    DirectHandle<BreakPoint> break_point) {
  // If there are no break points just ignore.
  if (IsUndefined(break_point_info->break_points())) return;
  // If there is a single break point clear it if it is the same.
  if (!IsFixedArray(break_point_info->break_points())) {
    if (IsEqual(Cast<BreakPoint>(break_point_info->break_points()),
                *break_point)) {
      break_point_info->set_break_points(
          ReadOnlyRoots(isolate).undefined_value());
    }
    return;
  }
  // If there are multiple break points shrink the array
  DCHECK(IsFixedArray(break_point_info->break_points()));
  DirectHandle<FixedArray> old_array(
      Cast<FixedArray>(break_point_info->break_points()), isolate);
  const uint32_t old_array_len = old_array->ulength().value();
  DCHECK_GT(old_array_len, 0);
  DirectHandle<FixedArray> new_array =
      isolate->factory()->NewFixedArray(old_array_len - 1);
  uint32_t found_count = 0;
  for (uint32_t i = 0; i < old_array_len; i++) {
    if (IsEqual(Cast<BreakPoint>(old_array->get(i)), *break_point)) {
      DCHECK_EQ(found_count, 0);
      found_count++;
    } else {
      new_array->set(i - found_count, old_array->get(i));
    }
  }
  // If the break point was found in the list change it.
  if (found_count > 0) break_point_info->set_break_points(*new_array);
}

// Add the specified break point object.
void BreakPointInfo::SetBreakPoint(
    Isolate* isolate, DirectHandle<BreakPointInfo> break_point_info,
    DirectHandle<BreakPoint> break_point) {
  // If there was no break point objects before just set it.
  if (IsUndefined(break_point_info->break_points())) {
    break_point_info->set_break_points(*break_point);
    return;
  }
  // If there was one break point object before replace with array.
  if (!IsFixedArray(break_point_info->break_points())) {
    if (IsEqual(Cast<BreakPoint>(break_point_info->break_points()),
                *break_point)) {
      return;
    }

    DirectHandle<FixedArray> array = isolate->factory()->NewFixedArray(2);
    array->set(0, break_point_info->break_points());
    array->set(1, *break_point);
    break_point_info->set_break_points(*array);
    return;
  }
  // If there was more than one break point before extend array.
  DirectHandle<FixedArray> old_array(
      Cast<FixedArray>(break_point_info->break_points()), isolate);
  const uint32_t old_array_len = old_array->ulength().value();
  DirectHandle<FixedArray> new_array =
      isolate->factory()->NewFixedArray(old_array_len + 1);
  for (uint32_t i = 0; i < old_array_len; i++) {
    // If the break point was there before just ignore.
    if (IsEqual(Cast<BreakPoint>(old_array->get(i)), *break_point)) return;
    new_array->set(i, old_array->get(i));
  }
  // Add the new break point.
  new_array->set(old_array_len, *break_point);
  break_point_info->set_break_points(*new_array);
}

bool BreakPointInfo::HasBreakPoint(
    Isolate* isolate, DirectHandle<BreakPointInfo> break_point_info,
    DirectHandle<BreakPoint> break_point) {
  // No break point.
  if (IsUndefined(break_point_info->break_points())) {
    return false;
  }
  // Single break point.
  if (!IsFixedArray(break_point_info->break_points())) {
    return IsEqual(Cast<BreakPoint>(break_point_info->break_points()),
                   *break_point);
  }
  // Multiple break points.
  Tagged<FixedArray> array = Cast<FixedArray>(break_point_info->break_points());
  const uint32_t array_len = array->ulength().value();
  for (uint32_t i = 0; i < array_len; i++) {
    if (IsEqual(Cast<BreakPoint>(array->get(i)), *break_point)) {
      return true;
    }
  }
  return false;
}

MaybeDirectHandle<BreakPoint> BreakPointInfo::GetBreakPointById(
    Isolate* isolate, DirectHandle<BreakPointInfo> break_point_info,
    int breakpoint_id) {
  // No break point.
  if (IsUndefined(break_point_info->break_points())) {
    return MaybeDirectHandle<BreakPoint>();
  }
  // Single break point.
  if (!IsFixedArray(break_point_info->break_points())) {
    Tagged<BreakPoint> breakpoint =
        Cast<BreakPoint>(break_point_info->break_points());
    if (breakpoint->id() == breakpoint_id) {
      return direct_handle(breakpoint, isolate);
    }
  } else {
    // Multiple break points.
    Tagged<FixedArray> array =
        Cast<FixedArray>(break_point_info->break_points());
    const uint32_t array_len = array->ulength().value();
    for (uint32_t i = 0; i < array_len; i++) {
      Tagged<BreakPoint> breakpoint = Cast<BreakPoint>(array->get(i));
      if (breakpoint->id() == breakpoint_id) {
        return direct_handle(breakpoint, isolate);
      }
    }
  }
  return MaybeDirectHandle<BreakPoint>();
}

// Get the number of break points.
uint32_t BreakPointInfo::GetBreakPointCount(Isolate* isolate) {
  // No break point.
  if (IsUndefined(break_points())) return 0;
  // Single break point.
  if (!IsFixedArray(break_points())) return 1;
  // Multiple break points.
  return Cast<FixedArray>(break_points())->ulength().value();
}

void CoverageInfo::InitializeSlot(int slot_index, int from_pos, int to_pos) {
  set_slots_start_source_position(slot_index, from_pos);
  set_slots_end_source_position(slot_index, to_pos);
  ResetBlockCount(slot_index);
  set_slots_padding(slot_index, 0);
}

void CoverageInfo::ResetBlockCount(int slot_index) {
  set_slots_block_count(slot_index, 0);
}

void CoverageInfo::CoverageInfoPrint(std::ostream& os,
                                     std::unique_ptr<char[]> function_name) {
  DisallowGarbageCollection no_gc;

  os << "Coverage info (";
  if (function_name == nullptr) {
    os << "{unknown}";
  } else if (strlen(function_name.get()) > 0) {
    os << function_name.get();
  } else {
    os << "{anonymous}";
  }
  os << "):" << std::endl;

  for (int i = 0; i < slot_count(); i++) {
    os << "{" << slots_start_source_position(i) << ","
       << slots_end_source_position(i) << "}" << std::endl;
  }
}

// static
int StackFrameInfo::GetSourcePosition(DirectHandle<StackFrameInfo> info) {
  if (IsScript(info->shared_or_script())) {
    return info->bytecode_offset_or_source_position();
  }
  Isolate* isolate = Isolate::Current();
  DirectHandle<SharedFunctionInfo> shared(
      Cast<SharedFunctionInfo>(info->shared_or_script()), isolate);
  SharedFunctionInfo::EnsureSourcePositionsAvailable(isolate, shared);
  int source_position = shared->abstract_code(isolate)->SourcePosition(
      isolate, info->bytecode_offset_or_source_position());
  info->set_shared_or_script(Cast<Script>(shared->script()));
  info->set_bytecode_offset_or_source_position(source_position);
  return source_position;
}

}  // namespace internal
}  // namespace v8
