/*
 * 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_DEX2OAT_DRIVER_COMPILED_METHOD_STORAGE_H_
#define ART_DEX2OAT_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 "driver/compiled_code_storage.h"
#include "utils/dedupe_set.h"
#include "utils/swap_space.h"

namespace art {

namespace linker {
class LinkerPatch;
}  // namespace linker

// TODO: Find a better name. This stores both method and non-method (thunks) code.
class CompiledMethodStorage final : public CompiledCodeStorage {
 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;

  CompiledMethod* CreateCompiledMethod(InstructionSet instruction_set,
                                       ArrayRef<const uint8_t> code,
                                       ArrayRef<const uint8_t> stack_map,
                                       ArrayRef<const uint8_t> cfi,
                                       ArrayRef<const linker::LinkerPatch> patches,
                                       bool is_intrinsic) override;

  // 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) override;

  // 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) override;

 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_DEX2OAT_DRIVER_COMPILED_METHOD_STORAGE_H_
