/*
 * Copyright (C) 2011 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_COMPILER_DRIVER_H_
#define ART_COMPILER_DRIVER_COMPILER_DRIVER_H_

#include <set>
#include <string>
#include <unordered_set>
#include <vector>

#include "arch/instruction_set.h"
#include "base/arena_allocator.h"
#include "base/array_ref.h"
#include "base/bit_utils.h"
#include "base/mutex.h"
#include "base/timing_logger.h"
#include "class_reference.h"
#include "compiler.h"
#include "dex_file.h"
#include "dex_file_types.h"
#include "driver/compiled_method_storage.h"
#include "jit/offline_profiling_info.h"
#include "invoke_type.h"
#include "method_reference.h"
#include "mirror/class.h"  // For mirror::Class::Status.
#include "os.h"
#include "runtime.h"
#include "safe_map.h"
#include "thread_pool.h"
#include "utils/atomic_method_ref_map.h"
#include "utils/dex_cache_arrays_layout.h"

namespace art {

namespace mirror {
class DexCache;
}  // namespace mirror

namespace verifier {
class MethodVerifier;
class VerifierDepsTest;
}  // namespace verifier

class BitVector;
class CompiledClass;
class CompiledMethod;
class CompilerOptions;
class DexCompilationUnit;
struct InlineIGetIPutData;
class InstructionSetFeatures;
class ParallelCompilationManager;
class ScopedObjectAccess;
template <class Allocator> class SrcMap;
class SrcMapElem;
using SwapSrcMap = SrcMap<SwapAllocator<SrcMapElem>>;
template<class T> class Handle;
class TimingLogger;
class VdexFile;
class VerificationResults;
class VerifiedMethod;

enum EntryPointCallingConvention {
  // ABI of invocations to a method's interpreter entry point.
  kInterpreterAbi,
  // ABI of calls to a method's native code, only used for native methods.
  kJniAbi,
  // ABI of calls to a method's quick code entry point.
  kQuickAbi
};

class CompilerDriver {
 public:
  // Create a compiler targeting the requested "instruction_set".
  // "image" should be true if image specific optimizations should be
  // enabled.  "image_classes" lets the compiler know what classes it
  // can assume will be in the image, with null implying all available
  // classes.
  CompilerDriver(const CompilerOptions* compiler_options,
                 VerificationResults* verification_results,
                 Compiler::Kind compiler_kind,
                 InstructionSet instruction_set,
                 const InstructionSetFeatures* instruction_set_features,
                 std::unordered_set<std::string>* image_classes,
                 std::unordered_set<std::string>* compiled_classes,
                 std::unordered_set<std::string>* compiled_methods,
                 size_t thread_count,
                 bool dump_stats,
                 bool dump_passes,
                 CumulativeLogger* timer,
                 int swap_fd,
                 const ProfileCompilationInfo* profile_compilation_info);

  ~CompilerDriver();

  // Set dex files that will be stored in the oat file after being compiled.
  void SetDexFilesForOatFile(const std::vector<const DexFile*>& dex_files) {
    dex_files_for_oat_file_ = &dex_files;
  }

  // Get dex file that will be stored in the oat file after being compiled.
  ArrayRef<const DexFile* const> GetDexFilesForOatFile() const {
    return (dex_files_for_oat_file_ != nullptr)
        ? ArrayRef<const DexFile* const>(*dex_files_for_oat_file_)
        : ArrayRef<const DexFile* const>();
  }

  void CompileAll(jobject class_loader,
                  const std::vector<const DexFile*>& dex_files,
                  TimingLogger* timings)
      REQUIRES(!Locks::mutator_lock_, !compiled_classes_lock_, !dex_to_dex_references_lock_);

  void CompileAll(jobject class_loader,
                  const std::vector<const DexFile*>& dex_files,
                  VdexFile* vdex_file,
                  TimingLogger* timings)
      REQUIRES(!Locks::mutator_lock_, !compiled_classes_lock_, !dex_to_dex_references_lock_);

  // Compile a single Method.
  void CompileOne(Thread* self, ArtMethod* method, TimingLogger* timings)
      REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!compiled_classes_lock_, !dex_to_dex_references_lock_);

  VerificationResults* GetVerificationResults() const {
    DCHECK(Runtime::Current()->IsAotCompiler());
    return verification_results_;
  }

  InstructionSet GetInstructionSet() const {
    return instruction_set_;
  }

  const InstructionSetFeatures* GetInstructionSetFeatures() const {
    return instruction_set_features_;
  }

  const CompilerOptions& GetCompilerOptions() const {
    return *compiler_options_;
  }

  Compiler* GetCompiler() const {
    return compiler_.get();
  }

  const std::unordered_set<std::string>* GetImageClasses() const {
    return image_classes_.get();
  }

  // Generate the trampolines that are invoked by unresolved direct methods.
  std::unique_ptr<const std::vector<uint8_t>> CreateJniDlsymLookup() const;
  std::unique_ptr<const std::vector<uint8_t>> CreateQuickGenericJniTrampoline() const;
  std::unique_ptr<const std::vector<uint8_t>> CreateQuickImtConflictTrampoline() const;
  std::unique_ptr<const std::vector<uint8_t>> CreateQuickResolutionTrampoline() const;
  std::unique_ptr<const std::vector<uint8_t>> CreateQuickToInterpreterBridge() const;

  CompiledClass* GetCompiledClass(ClassReference ref) const
      REQUIRES(!compiled_classes_lock_);

  CompiledMethod* GetCompiledMethod(MethodReference ref) const;
  size_t GetNonRelativeLinkerPatchCount() const;
  // Add a compiled method.
  void AddCompiledMethod(const MethodReference& method_ref,
                         CompiledMethod* const compiled_method,
                         size_t non_relative_linker_patch_count);

  void SetRequiresConstructorBarrier(Thread* self,
                                     const DexFile* dex_file,
                                     uint16_t class_def_index,
                                     bool requires)
      REQUIRES(!requires_constructor_barrier_lock_);
  bool RequiresConstructorBarrier(Thread* self,
                                  const DexFile* dex_file,
                                  uint16_t class_def_index)
      REQUIRES(!requires_constructor_barrier_lock_);

  // Are runtime access checks necessary in the compiled code?
  bool CanAccessTypeWithoutChecks(uint32_t referrer_idx,
                                  Handle<mirror::DexCache> dex_cache,
                                  dex::TypeIndex type_idx)
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Are runtime access and instantiable checks necessary in the code?
  // out_is_finalizable is set to whether the type is finalizable.
  bool CanAccessInstantiableTypeWithoutChecks(uint32_t referrer_idx,
                                              Handle<mirror::DexCache> dex_cache,
                                              dex::TypeIndex type_idx,
                                              bool* out_is_finalizable)
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Resolve compiling method's class. Returns null on failure.
  mirror::Class* ResolveCompilingMethodsClass(
      const ScopedObjectAccess& soa, Handle<mirror::DexCache> dex_cache,
      Handle<mirror::ClassLoader> class_loader, const DexCompilationUnit* mUnit)
      REQUIRES_SHARED(Locks::mutator_lock_);

  mirror::Class* ResolveClass(
      const ScopedObjectAccess& soa, Handle<mirror::DexCache> dex_cache,
      Handle<mirror::ClassLoader> class_loader, dex::TypeIndex type_index,
      const DexCompilationUnit* mUnit)
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Resolve a field. Returns null on failure, including incompatible class change.
  // NOTE: Unlike ClassLinker's ResolveField(), this method enforces is_static.
  ArtField* ResolveField(
      const ScopedObjectAccess& soa, Handle<mirror::DexCache> dex_cache,
      Handle<mirror::ClassLoader> class_loader, const DexCompilationUnit* mUnit,
      uint32_t field_idx, bool is_static)
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Resolve a field with a given dex file.
  ArtField* ResolveFieldWithDexFile(
      const ScopedObjectAccess& soa, Handle<mirror::DexCache> dex_cache,
      Handle<mirror::ClassLoader> class_loader, const DexFile* dex_file,
      uint32_t field_idx, bool is_static)
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Can we fast-path an IGET/IPUT access to an instance field? If yes, compute the field offset.
  std::pair<bool, bool> IsFastInstanceField(
      mirror::DexCache* dex_cache, mirror::Class* referrer_class,
      ArtField* resolved_field, uint16_t field_idx)
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Can we fast-path an SGET/SPUT access to a static field? If yes, compute the type index
  // of the declaring class in the referrer's dex file.
  std::pair<bool, bool> IsFastStaticField(mirror::DexCache* dex_cache,
                                          mirror::Class* referrer_class,
                                          ArtField* resolved_field,
                                          uint16_t field_idx,
                                          dex::TypeIndex* storage_index)
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Return whether the declaring class of `resolved_method` is
  // available to `referrer_class`. If this is true, compute the type
  // index of the declaring class in the referrer's dex file and
  // return it through the out argument `storage_index`; otherwise
  // return DexFile::kDexNoIndex through `storage_index`.
  bool IsClassOfStaticMethodAvailableToReferrer(mirror::DexCache* dex_cache,
                                                mirror::Class* referrer_class,
                                                ArtMethod* resolved_method,
                                                uint16_t method_idx,
                                                dex::TypeIndex* storage_index)
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Resolve a method. Returns null on failure, including incompatible class change.
  ArtMethod* ResolveMethod(
      ScopedObjectAccess& soa, Handle<mirror::DexCache> dex_cache,
      Handle<mirror::ClassLoader> class_loader, const DexCompilationUnit* mUnit,
      uint32_t method_idx, InvokeType invoke_type, bool check_incompatible_class_change = true)
      REQUIRES_SHARED(Locks::mutator_lock_);

  void ProcessedInstanceField(bool resolved);
  void ProcessedStaticField(bool resolved, bool local);

  // Can we fast path instance field access? Computes field's offset and volatility.
  bool ComputeInstanceFieldInfo(uint32_t field_idx, const DexCompilationUnit* mUnit, bool is_put,
                                MemberOffset* field_offset, bool* is_volatile)
      REQUIRES(!Locks::mutator_lock_);

  ArtField* ComputeInstanceFieldInfo(uint32_t field_idx,
                                             const DexCompilationUnit* mUnit,
                                             bool is_put,
                                             const ScopedObjectAccess& soa)
      REQUIRES_SHARED(Locks::mutator_lock_);


  const VerifiedMethod* GetVerifiedMethod(const DexFile* dex_file, uint32_t method_idx) const;
  bool IsSafeCast(const DexCompilationUnit* mUnit, uint32_t dex_pc);

  bool GetSupportBootImageFixup() const {
    return support_boot_image_fixup_;
  }

  void SetSupportBootImageFixup(bool support_boot_image_fixup) {
    support_boot_image_fixup_ = support_boot_image_fixup;
  }

  void SetCompilerContext(void* compiler_context) {
    compiler_context_ = compiler_context;
  }

  void* GetCompilerContext() const {
    return compiler_context_;
  }

  size_t GetThreadCount() const {
    return parallel_thread_count_;
  }

  bool GetDumpStats() const {
    return dump_stats_;
  }

  bool GetDumpPasses() const {
    return dump_passes_;
  }

  CumulativeLogger* GetTimingsLogger() const {
    return timings_logger_;
  }

  void SetDedupeEnabled(bool dedupe_enabled) {
    compiled_method_storage_.SetDedupeEnabled(dedupe_enabled);
  }

  bool DedupeEnabled() const {
    return compiled_method_storage_.DedupeEnabled();
  }

  // Checks if class specified by type_idx is one of the image_classes_
  bool IsImageClass(const char* descriptor) const;

  // Checks whether the provided class should be compiled, i.e., is in classes_to_compile_.
  bool IsClassToCompile(const char* descriptor) const;

  // Checks whether the provided method should be compiled, i.e., is in method_to_compile_.
  bool IsMethodToCompile(const MethodReference& method_ref) const;

  // Checks whether profile guided compilation is enabled and if the method should be compiled
  // according to the profile file.
  bool ShouldCompileBasedOnProfile(const MethodReference& method_ref) const;

  // Checks whether profile guided verification is enabled and if the method should be verified
  // according to the profile file.
  bool ShouldVerifyClassBasedOnProfile(const DexFile& dex_file, uint16_t class_idx) const;

  void RecordClassStatus(ClassReference ref, mirror::Class::Status status)
      REQUIRES(!compiled_classes_lock_);

  // Checks if the specified method has been verified without failures. Returns
  // false if the method is not in the verification results (GetVerificationResults).
  bool IsMethodVerifiedWithoutFailures(uint32_t method_idx,
                                       uint16_t class_def_idx,
                                       const DexFile& dex_file) const;

  // Get memory usage during compilation.
  std::string GetMemoryUsageString(bool extended) const;

  void SetHadHardVerifierFailure() {
    had_hard_verifier_failure_ = true;
  }

  Compiler::Kind GetCompilerKind() {
    return compiler_kind_;
  }

  CompiledMethodStorage* GetCompiledMethodStorage() {
    return &compiled_method_storage_;
  }

  // Can we assume that the klass is loaded?
  bool CanAssumeClassIsLoaded(mirror::Class* klass)
      REQUIRES_SHARED(Locks::mutator_lock_);

  bool MayInline(const DexFile* inlined_from, const DexFile* inlined_into) const {
    if (!kIsTargetBuild) {
      return MayInlineInternal(inlined_from, inlined_into);
    }
    return true;
  }

  void MarkForDexToDexCompilation(Thread* self, const MethodReference& method_ref)
      REQUIRES(!dex_to_dex_references_lock_);

  const BitVector* GetCurrentDexToDexMethods() const {
    return current_dex_to_dex_methods_;
  }

  // Compute constant code and method pointers when possible.
  void GetCodeAndMethodForDirectCall(const mirror::Class* referrer_class,
                                     ArtMethod* method,
                                     /* out */ uintptr_t* direct_code,
                                     /* out */ uintptr_t* direct_method)
      REQUIRES_SHARED(Locks::mutator_lock_);

 private:
  // Return whether the declaring class of `resolved_member` is
  // available to `referrer_class` for read or write access using two
  // Boolean values returned as a pair. If is true at least for read
  // access, compute the type index of the declaring class in the
  // referrer's dex file and return it through the out argument
  // `storage_index`; otherwise return DexFile::kDexNoIndex through
  // `storage_index`.
  template <typename ArtMember>
  std::pair<bool, bool> IsClassOfStaticMemberAvailableToReferrer(mirror::DexCache* dex_cache,
                                                                 mirror::Class* referrer_class,
                                                                 ArtMember* resolved_member,
                                                                 uint16_t member_idx,
                                                                 dex::TypeIndex* storage_index)
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Can `referrer_class` access the resolved `member`?
  // Dispatch call to mirror::Class::CanAccessResolvedField or
  // mirror::Class::CanAccessResolvedMember depending on the value of
  // ArtMember.
  template <typename ArtMember>
  static bool CanAccessResolvedMember(mirror::Class* referrer_class,
                                      mirror::Class* access_to,
                                      ArtMember* member,
                                      mirror::DexCache* dex_cache,
                                      uint32_t field_idx)
      REQUIRES_SHARED(Locks::mutator_lock_);

  mirror::ClassLoader* GetClassLoader(const ScopedObjectAccess& soa,
                                      const DexCompilationUnit* mUnit)
    REQUIRES_SHARED(Locks::mutator_lock_);

 private:
  void PreCompile(jobject class_loader,
                  const std::vector<const DexFile*>& dex_files,
                  TimingLogger* timings)
      REQUIRES(!Locks::mutator_lock_, !compiled_classes_lock_);

  void LoadImageClasses(TimingLogger* timings) REQUIRES(!Locks::mutator_lock_);

  // Attempt to resolve all type, methods, fields, and strings
  // referenced from code in the dex file following PathClassLoader
  // ordering semantics.
  void Resolve(jobject class_loader,
               const std::vector<const DexFile*>& dex_files,
               TimingLogger* timings)
      REQUIRES(!Locks::mutator_lock_);
  void ResolveDexFile(jobject class_loader,
                      const DexFile& dex_file,
                      const std::vector<const DexFile*>& dex_files,
                      ThreadPool* thread_pool,
                      size_t thread_count,
                      TimingLogger* timings)
      REQUIRES(!Locks::mutator_lock_);

  void Verify(jobject class_loader,
              const std::vector<const DexFile*>& dex_files,
              TimingLogger* timings);

  void VerifyDexFile(jobject class_loader,
                     const DexFile& dex_file,
                     const std::vector<const DexFile*>& dex_files,
                     ThreadPool* thread_pool,
                     size_t thread_count,
                     TimingLogger* timings)
      REQUIRES(!Locks::mutator_lock_);

  void SetVerified(jobject class_loader,
                   const std::vector<const DexFile*>& dex_files,
                   TimingLogger* timings);
  void SetVerifiedDexFile(jobject class_loader,
                          const DexFile& dex_file,
                          const std::vector<const DexFile*>& dex_files,
                          ThreadPool* thread_pool,
                          size_t thread_count,
                          TimingLogger* timings)
      REQUIRES(!Locks::mutator_lock_);

  void InitializeClasses(jobject class_loader,
                         const std::vector<const DexFile*>& dex_files,
                         TimingLogger* timings)
      REQUIRES(!Locks::mutator_lock_, !compiled_classes_lock_);
  void InitializeClasses(jobject class_loader,
                         const DexFile& dex_file,
                         const std::vector<const DexFile*>& dex_files,
                         TimingLogger* timings)
      REQUIRES(!Locks::mutator_lock_, !compiled_classes_lock_);

  void UpdateImageClasses(TimingLogger* timings) REQUIRES(!Locks::mutator_lock_);

  void Compile(jobject class_loader,
               const std::vector<const DexFile*>& dex_files,
               TimingLogger* timings) REQUIRES(!dex_to_dex_references_lock_);
  void CompileDexFile(jobject class_loader,
                      const DexFile& dex_file,
                      const std::vector<const DexFile*>& dex_files,
                      ThreadPool* thread_pool,
                      size_t thread_count,
                      TimingLogger* timings)
      REQUIRES(!Locks::mutator_lock_);

  bool MayInlineInternal(const DexFile* inlined_from, const DexFile* inlined_into) const;

  void InitializeThreadPools();
  void FreeThreadPools();
  void CheckThreadPools();

  bool RequiresConstructorBarrier(const DexFile& dex_file, uint16_t class_def_idx) const;

  const CompilerOptions* const compiler_options_;
  VerificationResults* const verification_results_;

  std::unique_ptr<Compiler> compiler_;
  Compiler::Kind compiler_kind_;

  const InstructionSet instruction_set_;
  const InstructionSetFeatures* const instruction_set_features_;

  // All class references that require constructor barriers. If the class reference is not in the
  // set then the result has not yet been computed.
  mutable ReaderWriterMutex requires_constructor_barrier_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
  std::map<ClassReference, bool> requires_constructor_barrier_
      GUARDED_BY(requires_constructor_barrier_lock_);

  typedef SafeMap<const ClassReference, CompiledClass*> ClassTable;
  // All class references that this compiler has compiled.
  mutable Mutex compiled_classes_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
  ClassTable compiled_classes_ GUARDED_BY(compiled_classes_lock_);

  typedef AtomicMethodRefMap<CompiledMethod*> MethodTable;

 private:
  // All method references that this compiler has compiled.
  MethodTable compiled_methods_;

  // Number of non-relative patches in all compiled methods. These patches need space
  // in the .oat_patches ELF section if requested in the compiler options.
  Atomic<size_t> non_relative_linker_patch_count_;

  // If image_ is true, specifies the classes that will be included in the image.
  // Note if image_classes_ is null, all classes are included in the image.
  std::unique_ptr<std::unordered_set<std::string>> image_classes_;

  // Specifies the classes that will be compiled. Note that if classes_to_compile_ is null,
  // all classes are eligible for compilation (duplication filters etc. will still apply).
  // This option may be restricted to the boot image, depending on a flag in the implementation.
  std::unique_ptr<std::unordered_set<std::string>> classes_to_compile_;

  // Specifies the methods that will be compiled. Note that if methods_to_compile_ is null,
  // all methods are eligible for compilation (compilation filters etc. will still apply).
  // This option may be restricted to the boot image, depending on a flag in the implementation.
  std::unique_ptr<std::unordered_set<std::string>> methods_to_compile_;

  bool had_hard_verifier_failure_;

  // A thread pool that can (potentially) run tasks in parallel.
  std::unique_ptr<ThreadPool> parallel_thread_pool_;
  size_t parallel_thread_count_;

  // A thread pool that guarantees running single-threaded on the main thread.
  std::unique_ptr<ThreadPool> single_thread_pool_;

  class AOTCompilationStats;
  std::unique_ptr<AOTCompilationStats> stats_;

  bool dump_stats_;
  const bool dump_passes_;

  CumulativeLogger* const timings_logger_;

  typedef void (*CompilerCallbackFn)(CompilerDriver& driver);
  typedef MutexLock* (*CompilerMutexLockFn)(CompilerDriver& driver);

  void* compiler_context_;

  bool support_boot_image_fixup_;

  // List of dex files that will be stored in the oat file.
  const std::vector<const DexFile*>* dex_files_for_oat_file_;

  CompiledMethodStorage compiled_method_storage_;

  // Info for profile guided compilation.
  const ProfileCompilationInfo* const profile_compilation_info_;

  size_t max_arena_alloc_;

  // Data for delaying dex-to-dex compilation.
  Mutex dex_to_dex_references_lock_;
  // In the first phase, dex_to_dex_references_ collects methods for dex-to-dex compilation.
  class DexFileMethodSet;
  std::vector<DexFileMethodSet> dex_to_dex_references_ GUARDED_BY(dex_to_dex_references_lock_);
  // In the second phase, current_dex_to_dex_methods_ points to the BitVector with method
  // indexes for dex-to-dex compilation in the current dex file.
  const BitVector* current_dex_to_dex_methods_;

  friend class CompileClassVisitor;
  friend class DexToDexDecompilerTest;
  friend class verifier::VerifierDepsTest;
  DISALLOW_COPY_AND_ASSIGN(CompilerDriver);
};

}  // namespace art

#endif  // ART_COMPILER_DRIVER_COMPILER_DRIVER_H_
