/*
 * Copyright (C) 2014 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_DEX_VERIFIED_METHOD_H_
#define ART_COMPILER_DEX_VERIFIED_METHOD_H_

#include <vector>

#include "base/mutex.h"
#include "dex_file.h"
#include "method_reference.h"
#include "safe_map.h"

namespace art {

namespace verifier {
class MethodVerifier;
}  // namespace verifier

class VerifiedMethod {
 public:
  // Cast elision set type.
  // Since we're adding the dex PCs to the set in increasing order, a sorted vector
  // is better for performance (not just memory usage), especially for large sets.
  typedef std::vector<uint32_t> SafeCastSet;

  // Devirtualization map type maps dex offset to concrete method reference.
  typedef SafeMap<uint32_t, MethodReference> DevirtualizationMap;

  // Devirtualization map type maps dex offset to field / method idx.
  typedef SafeMap<uint32_t, DexFileReference> DequickenMap;

  static const VerifiedMethod* Create(verifier::MethodVerifier* method_verifier, bool compile)
      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
  ~VerifiedMethod() = default;

  const std::vector<uint8_t>& GetDexGcMap() const {
    return dex_gc_map_;
  }

  const DevirtualizationMap& GetDevirtMap() const {
    return devirt_map_;
  }

  const SafeCastSet& GetSafeCastSet() const {
    return safe_cast_set_;
  }

  // Returns the devirtualization target method, or null if none.
  const MethodReference* GetDevirtTarget(uint32_t dex_pc) const;

  // Returns the dequicken field / method for a quick invoke / field get. Returns null if there is
  // no entry for that dex pc.
  const DexFileReference* GetDequickenIndex(uint32_t dex_pc) const;

  // Returns true if the cast can statically be verified to be redundant
  // by using the check-cast elision peephole optimization in the verifier.
  bool IsSafeCast(uint32_t pc) const;

  // Returns true if there were any errors during verification.
  bool HasVerificationFailures() const {
    return has_verification_failures_;
  }

  void SetStringInitPcRegMap(SafeMap<uint32_t, std::set<uint32_t>>& string_init_pc_reg_map) {
    string_init_pc_reg_map_ = string_init_pc_reg_map;
  }
  const SafeMap<uint32_t, std::set<uint32_t>>& GetStringInitPcRegMap() const {
    return string_init_pc_reg_map_;
  }

 private:
  VerifiedMethod() = default;

  /*
   * Generate the GC map for a method that has just been verified (i.e. we're doing this as part of
   * verification). For type-precise determination we have all the data we need, so we just need to
   * encode it in some clever fashion.
   * Stores the data in dex_gc_map_, returns true on success and false on failure.
   */
  bool GenerateGcMap(verifier::MethodVerifier* method_verifier);

  // Verify that the GC map associated with method_ is well formed.
  static void VerifyGcMap(verifier::MethodVerifier* method_verifier,
                          const std::vector<uint8_t>& data);

  // Compute sizes for GC map data.
  static void ComputeGcMapSizes(verifier::MethodVerifier* method_verifier,
                                size_t* gc_points, size_t* ref_bitmap_bits, size_t* log2_max_gc_pc);

  // Generate devirtualizaion map into devirt_map_.
  void GenerateDevirtMap(verifier::MethodVerifier* method_verifier)
      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);

  // Generate dequickening map into dequicken_map_. Returns false if there is an error.
  bool GenerateDequickenMap(verifier::MethodVerifier* method_verifier)
      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);

  // Generate safe case set into safe_cast_set_.
  void GenerateSafeCastSet(verifier::MethodVerifier* method_verifier)
      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);

  std::vector<uint8_t> dex_gc_map_;
  DevirtualizationMap devirt_map_;
  // Dequicken map is required for compiling quickened byte codes. The quicken maps from
  // dex PC to dex method index or dex field index based on the instruction.
  DequickenMap dequicken_map_;
  SafeCastSet safe_cast_set_;

  bool has_verification_failures_;

  // Copy of mapping generated by verifier of dex PCs of string init invocations
  // to the set of other registers that the receiver has been copied into.
  SafeMap<uint32_t, std::set<uint32_t>> string_init_pc_reg_map_;
};

}  // namespace art

#endif  // ART_COMPILER_DEX_VERIFIED_METHOD_H_
