// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#include "vm/reverse_pc_lookup_cache.h"

#include "vm/isolate.h"
#include "vm/object.h"
#include "vm/object_store.h"

namespace dart {

CodePtr ReversePc::LookupInGroup(IsolateGroup* group,
                                 uword pc,
                                 bool is_return_address) {
#if defined(DART_PRECOMPILED_RUNTIME)
  // This can run in the middle of GC and must not allocate handles.
  NoSafepointScope no_safepoint;

  if (is_return_address) {
    pc--;
  }

  // This expected number of tables is low, so we go through them linearly. If
  // this changes, would could sort the table list during deserialization and
  // binary search for the table.
  GrowableObjectArrayPtr tables = group->object_store()->code_order_tables();
  intptr_t tables_length = Smi::Value(tables->untag()->length_);
  for (intptr_t i = 0; i < tables_length; i++) {
    ArrayPtr table =
        static_cast<ArrayPtr>(tables->untag()->data_->untag()->data()[i]);
    intptr_t lo = 0;
    intptr_t hi = Smi::Value(table->untag()->length_) - 1;

    // Fast check if pc belongs to this table.
    if (lo > hi) {
      continue;
    }
    CodePtr first = static_cast<CodePtr>(table->untag()->data()[lo]);
    if (pc < Code::PayloadStartOf(first)) {
      continue;
    }
    CodePtr last = static_cast<CodePtr>(table->untag()->data()[hi]);
    if (pc >= (Code::PayloadStartOf(last) + Code::PayloadSizeOf(last))) {
      continue;
    }

    // Binary search within the table for the matching Code.
    while (lo <= hi) {
      intptr_t mid = (hi - lo + 1) / 2 + lo;
      ASSERT(mid >= lo);
      ASSERT(mid <= hi);
      CodePtr code = static_cast<CodePtr>(table->untag()->data()[mid]);
      uword code_start = Code::PayloadStartOf(code);
      uword code_end = code_start + Code::PayloadSizeOf(code);
      if (pc < code_start) {
        hi = mid - 1;
      } else if (pc >= code_end) {
        lo = mid + 1;
      } else {
        return code;
      }
    }
  }
#endif  // defined(DART_PRECOMPILED_RUNTIME)

  return Code::null();
}

CodePtr ReversePc::Lookup(IsolateGroup* group,
                          uword pc,
                          bool is_return_address) {
  ASSERT(FLAG_precompiled_mode && FLAG_use_bare_instructions);
  NoSafepointScope no_safepoint;

  CodePtr code = LookupInGroup(group, pc, is_return_address);
  if (code == Code::null()) {
    code = LookupInGroup(Dart::vm_isolate_group(), pc, is_return_address);
  }
  return code;
}

CompressedStackMapsPtr ReversePc::FindCompressedStackMaps(
    IsolateGroup* group,
    uword pc,
    bool is_return_address,
    uword* code_start) {
  ASSERT(FLAG_precompiled_mode && FLAG_use_bare_instructions);
  NoSafepointScope no_safepoint;

  CodePtr code = Lookup(group, pc, is_return_address);
  if (code != Code::null()) {
    *code_start = Code::PayloadStartOf(code);
    return code->untag()->compressed_stackmaps();
  }

  *code_start = 0;
  return CompressedStackMaps::null();
}

}  // namespace dart
