// 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"
#include "vm/stub_code.h"

namespace dart {

ObjectPtr ReversePc::FindCodeDescriptorInGroup(IsolateGroup* group,
                                               uword pc,
                                               bool is_return_address,
                                               uword* code_start) {
#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 (one per loading unit), 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()->instructions_tables();
  intptr_t tables_length = Smi::Value(tables->untag()->length());
  for (intptr_t i = 0; i < tables_length; i++) {
    InstructionsTablePtr table = static_cast<InstructionsTablePtr>(
        tables->untag()->data()->untag()->element(i));
    intptr_t index = InstructionsTable::FindEntry(table, pc);
    if (index >= 0) {
      *code_start = InstructionsTable::PayloadStartAt(table, index);
      return InstructionsTable::DescriptorAt(table, index);
    }
  }
#endif  // defined(DART_PRECOMPILED_RUNTIME)

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

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

  ObjectPtr code_descriptor =
      FindCodeDescriptorInGroup(group, pc, is_return_address, code_start);
  if (code_descriptor == Object::null()) {
    code_descriptor = FindCodeDescriptorInGroup(Dart::vm_isolate_group(), pc,
                                                is_return_address, code_start);
  }
  return code_descriptor;
}

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

  uword code_start;
  ObjectPtr code_descriptor =
      FindCodeDescriptor(group, pc, is_return_address, &code_start);
  if (code_descriptor != Object::null()) {
    if (!code_descriptor->IsCode()) {
      ASSERT(StubCode::UnknownDartCode().PayloadStart() == 0);
      ASSERT(StubCode::UnknownDartCode().Size() == kUwordMax);
      ASSERT(StubCode::UnknownDartCode().IsFunctionCode());
      ASSERT(StubCode::UnknownDartCode().IsUnknownDartCode());
      code_descriptor = StubCode::UnknownDartCode().ptr();
    }
  }
  return static_cast<CodePtr>(code_descriptor);
}

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;

  ObjectPtr code_descriptor =
      FindCodeDescriptor(group, pc, is_return_address, code_start);
  if (code_descriptor != Object::null()) {
    if (code_descriptor->IsCode()) {
      CodePtr code = static_cast<CodePtr>(code_descriptor);
      ASSERT(*code_start == Code::PayloadStartOf(code));
      return code->untag()->compressed_stackmaps();
    } else {
      ASSERT(code_descriptor->IsCompressedStackMaps());
      return static_cast<CompressedStackMapsPtr>(code_descriptor);
    }
  }

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

}  // namespace dart
