// Copyright (c) 2020, 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/closure_functions_cache.h"

#include "vm/compiler/jit/compiler.h"
#include "vm/hash_table.h"
#include "vm/object.h"
#include "vm/object_store.h"

namespace dart {

class FunctionHashMapTraits {
 public:
  static const char* Name() { return "FunctionMapTraits"; }
  static bool ReportStats() { return false; }
  static bool IsMatch(const Object& a, const Object& b) {
    return a.ptr() == b.ptr();
  }
  static uword Hash(const Object& key) { return Function::Cast(key).Hash(); }
};

using FunctionHashMap = UnorderedHashMap<FunctionHashMapTraits>;

FunctionPtr ClosureFunctionsCache::LookupClosureFunction(
    const Function& member_function,
    intptr_t kernel_offset) {
  ASSERT(!member_function.HasBytecode());
  auto thread = Thread::Current();
  SafepointReadRwLocker ml(thread, thread->isolate_group()->program_lock());
  return LookupClosureFunctionLocked(member_function, kernel_offset);
}

FunctionPtr ClosureFunctionsCache::LookupClosureFunctionLocked(
    const Function& member_function,
    intptr_t kernel_offset) {
  ASSERT(!member_function.HasBytecode());
  auto thread = Thread::Current();
  auto zone = thread->zone();
  auto object_store = thread->isolate_group()->object_store();

  DEBUG_ASSERT(
      thread->isolate_group()->program_lock()->IsCurrentThreadReader());

  auto& map_array =
      Array::Handle(zone, object_store->closure_functions_table());
  if (map_array.IsNull()) {
    return Function::null();
  }

  FunctionHashMap map(zone, map_array.ptr());
  map_array ^= map.GetOrNull(member_function);
  map.Release();

  if (map_array.IsNull()) {
    return Function::null();
  }

  auto& result = Function::Handle(zone);
  IntHashMap map2(zone, map_array.ptr());
  result ^= map2.GetOrNull(Smi::Handle(zone, Smi::New(kernel_offset)));
  map2.Release();

  return result.ptr();
}

void ClosureFunctionsCache::AddClosureFunctionLocked(
    const Function& function,
    bool allow_implicit_closure_functions /* = false */) {
  ASSERT(!Compiler::IsBackgroundCompilation());

  auto thread = Thread::Current();
  auto zone = thread->zone();
  auto object_store = thread->isolate_group()->object_store();

  DEBUG_ASSERT(
      thread->isolate_group()->program_lock()->IsCurrentThreadWriter());

  auto& closures =
      GrowableObjectArray::Handle(zone, object_store->closure_functions());
  if (closures.IsNull()) {
    closures = GrowableObjectArray::New();
    object_store->set_closure_functions(closures);
  }

  ASSERT(allow_implicit_closure_functions ||
         function.IsNonImplicitClosureFunction());
  closures.Add(function, Heap::kOld);

  if (allow_implicit_closure_functions || function.HasBytecode()) {
    return;
  }

  const Function& member_function =
      Function::Handle(zone, function.GetOutermostFunction());
  ASSERT(function.kernel_offset() > 0);

  auto& map_array =
      Array::Handle(zone, object_store->closure_functions_table());
  if (map_array.IsNull()) {
    map_array = HashTables::New<FunctionHashMap>(16, Heap::kOld);
  }
  FunctionHashMap map(zone, map_array.ptr());
  map_array ^= map.GetOrNull(member_function);
  if (map_array.IsNull()) {
    map_array = HashTables::New<IntHashMap>(4, Heap::kOld);
  }
  IntHashMap map2(zone, map_array.ptr());
  map2.UpdateOrInsert(Smi::Handle(zone, Smi::New(function.kernel_offset())),
                      function);
  map.UpdateOrInsert(member_function, map2.Release());
  object_store->set_closure_functions_table(map.Release());
}

intptr_t ClosureFunctionsCache::FindClosureIndex(const Function& needle) {
  auto thread = Thread::Current();
  auto zone = thread->zone();
  auto object_store = thread->isolate_group()->object_store();

  SafepointReadRwLocker ml(thread, thread->isolate_group()->program_lock());

  const auto& closures_array =
      GrowableObjectArray::Handle(zone, object_store->closure_functions());
  if (!closures_array.IsNull()) {
    intptr_t num_closures = closures_array.Length();
    for (intptr_t i = 0; i < num_closures; i++) {
      if (closures_array.At(i) == needle.ptr()) {
        return i;
      }
    }
  }
  return -1;
}

FunctionPtr ClosureFunctionsCache::ClosureFunctionFromIndex(intptr_t idx) {
  auto thread = Thread::Current();
  auto zone = thread->zone();
  auto object_store = thread->isolate_group()->object_store();

  SafepointReadRwLocker ml(thread, thread->isolate_group()->program_lock());

  const auto& closures_array =
      GrowableObjectArray::Handle(zone, object_store->closure_functions());
  if (idx < 0 || closures_array.IsNull() || idx >= closures_array.Length()) {
    return Function::null();
  }
  return Function::RawCast(closures_array.At(idx));
}

void ClosureFunctionsCache::ForAllClosureFunctions(
    std::function<bool(const Function&)> callback) {
  auto thread = Thread::Current();
  auto zone = thread->zone();
  auto object_store = thread->isolate_group()->object_store();

  auto& current_data = Array::Handle(zone);
  auto& entry = Function::Handle(zone);

  // NOTE: Inner functions may get added to the closures array while iterating -
  // we guarantee that any closure functions added on this thread by a
  // [callback] call will be visited as well.
  //
  // We avoid holding a lock while accessing the closures array, since often
  // times [callback] will do very heavy things (e.g. compiling the function).
  //
  // This means we can possibly miss a concurrently added closure function -
  // which the caller should be ok with (or it guarantees that this cannot
  // happen).
  const auto& closures =
      GrowableObjectArray::Handle(zone, object_store->closure_functions());
  if (closures.IsNull()) {
    return;
  }

  if (!thread->IsInStoppedMutatorsScope()) {
    // The empty read locker scope will implicitly issue an acquire memory
    // fence, which means any closure functions added so far will be visible and
    // iterated further down.
    SafepointReadRwLocker ml(thread, thread->isolate_group()->program_lock());
  }

  // We have an outer loop to ensure any new closure functions added by
  // [callback] will be iterated as well.
  intptr_t i = 0;
  while (true) {
    intptr_t current_length = closures.Length();
    if (i == current_length) break;

    current_data = closures.data();
    if (current_data.Length() < current_length) {
      current_length = current_data.Length();
    }

    for (; i < current_length; ++i) {
      entry ^= current_data.At(i);
      if (!callback(entry)) {
        return;  // Stop iteration.
      }
    }
  }
}

}  // namespace dart
