/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef ART_COMPILER_DRIVER_COMPILED_METHOD_STORAGE_H_
#define ART_COMPILER_DRIVER_COMPILED_METHOD_STORAGE_H_

#include <iosfwd>
#include <map>
#include <memory>

#include "base/array_ref.h"
#include "base/length_prefixed_array.h"
#include "base/macros.h"
#include "utils/dedupe_set.h"
#include "utils/swap_space.h"

namespace art {

namespace linker {
class LinkerPatch;
}  // namespace linker

class CompiledMethodStorage {
 public:
  explicit CompiledMethodStorage(int swap_fd);
  ~CompiledMethodStorage();

  void DumpMemoryUsage(std::ostream& os, bool extended) const;

  void SetDedupeEnabled(bool dedupe_enabled) {
    dedupe_enabled_ = dedupe_enabled;
  }
  bool DedupeEnabled() const {
    return dedupe_enabled_;
  }

  SwapAllocator<void> GetSwapSpaceAllocator() {
    return SwapAllocator<void>(swap_space_.get());
  }

  const LengthPrefixedArray<uint8_t>* DeduplicateCode(const ArrayRef<const uint8_t>& code);
  void ReleaseCode(const LengthPrefixedArray<uint8_t>* code);
  size_t UniqueCodeEntries() const;

  const LengthPrefixedArray<uint8_t>* DeduplicateVMapTable(const ArrayRef<const uint8_t>& table);
  void ReleaseVMapTable(const LengthPrefixedArray<uint8_t>* table);
  size_t UniqueVMapTableEntries() const;

  const LengthPrefixedArray<uint8_t>* DeduplicateCFIInfo(const ArrayRef<const uint8_t>& cfi_info);
  void ReleaseCFIInfo(const LengthPrefixedArray<uint8_t>* cfi_info);
  size_t UniqueCFIInfoEntries() const;

  const LengthPrefixedArray<linker::LinkerPatch>* DeduplicateLinkerPatches(
      const ArrayRef<const linker::LinkerPatch>& linker_patches);
  void ReleaseLinkerPatches(const LengthPrefixedArray<linker::LinkerPatch>* linker_patches);
  size_t UniqueLinkerPatchesEntries() const;

  // Returns the code associated with the given patch.
  // If the code has not been set, returns empty data.
  // If `debug_name` is not null, stores the associated debug name in `*debug_name`.
  ArrayRef<const uint8_t> GetThunkCode(const linker::LinkerPatch& linker_patch,
                                       /*out*/ std::string* debug_name = nullptr);

  // Sets the code and debug name associated with the given patch.
  void SetThunkCode(const linker::LinkerPatch& linker_patch,
                    ArrayRef<const uint8_t> code,
                    const std::string& debug_name);

 private:
  class ThunkMapKey;
  class ThunkMapValue;
  using ThunkMapValueType = std::pair<const ThunkMapKey, ThunkMapValue>;
  using ThunkMap = std::map<ThunkMapKey,
                            ThunkMapValue,
                            std::less<ThunkMapKey>,
                            SwapAllocator<ThunkMapValueType>>;
  static_assert(std::is_same<ThunkMapValueType, ThunkMap::value_type>::value, "Value type check.");

  static ThunkMapKey GetThunkMapKey(const linker::LinkerPatch& linker_patch);

  template <typename T, typename DedupeSetType>
  const LengthPrefixedArray<T>* AllocateOrDeduplicateArray(const ArrayRef<const T>& data,
                                                           DedupeSetType* dedupe_set);

  template <typename T>
  void ReleaseArrayIfNotDeduplicated(const LengthPrefixedArray<T>* array);

  // DeDuplication data structures.
  template <typename ContentType>
  class DedupeHashFunc;

  template <typename T>
  class LengthPrefixedArrayAlloc;

  template <typename T>
  using ArrayDedupeSet = DedupeSet<ArrayRef<const T>,
                                   LengthPrefixedArray<T>,
                                   LengthPrefixedArrayAlloc<T>,
                                   size_t,
                                   DedupeHashFunc<const T>,
                                   4>;

  // Swap pool and allocator used for native allocations. May be file-backed. Needs to be first
  // as other fields rely on this.
  std::unique_ptr<SwapSpace> swap_space_;

  bool dedupe_enabled_;

  ArrayDedupeSet<uint8_t> dedupe_code_;
  ArrayDedupeSet<uint8_t> dedupe_vmap_table_;
  ArrayDedupeSet<uint8_t> dedupe_cfi_info_;
  ArrayDedupeSet<linker::LinkerPatch> dedupe_linker_patches_;

  Mutex thunk_map_lock_;
  ThunkMap thunk_map_ GUARDED_BY(thunk_map_lock_);

  DISALLOW_COPY_AND_ASSIGN(CompiledMethodStorage);
};

}  // namespace art

#endif  // ART_COMPILER_DRIVER_COMPILED_METHOD_STORAGE_H_
