/*
 * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 *
 */

#ifndef SHARE_CODE_CODECACHE_HPP
#define SHARE_CODE_CODECACHE_HPP

#include "code/codeBlob.hpp"
#include "code/nmethod.hpp"
#include "gc/shared/gcBehaviours.hpp"
#include "memory/allocation.hpp"
#include "memory/heap.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/oopsHierarchy.hpp"
#include "runtime/mutexLocker.hpp"
#include "utilities/numberSeq.hpp"

// The CodeCache implements the code cache for various pieces of generated
// code, e.g., compiled java methods, runtime stubs, transition frames, etc.
// The entries in the CodeCache are all CodeBlob's.

// -- Implementation --
// The CodeCache consists of one or more CodeHeaps, each of which contains
// CodeBlobs of a specific CodeBlobType. Currently heaps for the following
// types are available:
//  - Non-nmethods: Non-nmethods like Buffers, Adapters and Runtime Stubs
//  - Profiled nmethods: nmethods that are profiled, i.e., those
//    executed at level 2 or 3
//  - Non-Profiled nmethods: nmethods that are not profiled, i.e., those
//    executed at level 1 or 4 and native methods
//  - All: Used for code of all types if code cache segmentation is disabled.
//
// In the rare case of the non-nmethod code heap getting full, non-nmethod code
// will be stored in the non-profiled code heap as a fallback solution.
//
// Depending on the availability of compilers and compilation mode there
// may be fewer heaps. The size of the code heaps depends on the values of
// ReservedCodeCacheSize, NonProfiledCodeHeapSize and ProfiledCodeHeapSize
// (see CodeCache::heap_available(..) and CodeCache::initialize_heaps(..)
// for details).
//
// Code cache segmentation is controlled by the flag SegmentedCodeCache.
// If turned off, all code types are stored in a single code heap. By default
// code cache segmentation is turned on if tiered mode is enabled and
// ReservedCodeCacheSize >= 240 MB.
//
// All methods of the CodeCache accepting a CodeBlobType only apply to
// CodeBlobs of the given type. For example, iteration over the
// CodeBlobs of a specific type can be done by using CodeCache::first_blob(..)
// and CodeCache::next_blob(..) and providing the corresponding CodeBlobType.
//
// IMPORTANT: If you add new CodeHeaps to the code cache or change the
// existing ones, make sure to adapt the dtrace scripts (jhelper.d) for
// Solaris and BSD.

class ExceptionCache;
class KlassDepChange;
class OopClosure;
class ShenandoahParallelCodeHeapIterator;
class NativePostCallNop;
class DeoptimizationScope;

class CodeCache : AllStatic {
  friend class VMStructs;
  friend class JVMCIVMStructs;
  template <class T, class Filter, bool is_compiled_method> friend class CodeBlobIterator;
  friend class WhiteBox;
  friend class CodeCacheLoader;
  friend class ShenandoahParallelCodeHeapIterator;
 private:
  // CodeHeaps of the cache
  static GrowableArray<CodeHeap*>* _heaps;
  static GrowableArray<CodeHeap*>* _compiled_heaps;
  static GrowableArray<CodeHeap*>* _nmethod_heaps;
  static GrowableArray<CodeHeap*>* _allocable_heaps;

  static address _low_bound;                                 // Lower bound of CodeHeap addresses
  static address _high_bound;                                // Upper bound of CodeHeap addresses
  static volatile int _number_of_nmethods_with_dependencies; // Total number of nmethods with dependencies

  static uint8_t           _unloading_cycle;          // Global state for recognizing old nmethods that need to be unloaded
  static uint64_t          _gc_epoch;                 // Global state for tracking when nmethods were found to be on-stack
  static uint64_t          _cold_gc_count;            // Global state for determining how many GCs are needed before an nmethod is cold
  static size_t            _last_unloading_used;
  static double            _last_unloading_time;
  static TruncatedSeq      _unloading_gc_intervals;
  static TruncatedSeq      _unloading_allocation_rates;
  static volatile bool     _unloading_threshold_gc_requested;

  static ExceptionCache* volatile _exception_cache_purge_list;

  // CodeHeap management
  static void initialize_heaps();                             // Initializes the CodeHeaps
  // Check the code heap sizes set by the user via command line
  static void check_heap_sizes(size_t non_nmethod_size, size_t profiled_size, size_t non_profiled_size, size_t cache_size, bool all_set);
  // Creates a new heap with the given name and size, containing CodeBlobs of the given type
  static void add_heap(ReservedSpace rs, const char* name, CodeBlobType code_blob_type);
  static CodeHeap* get_code_heap_containing(void* p);         // Returns the CodeHeap containing the given pointer, or nullptr
  static CodeHeap* get_code_heap(const void* cb);             // Returns the CodeHeap for the given CodeBlob
  static CodeHeap* get_code_heap(CodeBlobType code_blob_type);         // Returns the CodeHeap for the given CodeBlobType
  // Returns the name of the VM option to set the size of the corresponding CodeHeap
  static const char* get_code_heap_flag_name(CodeBlobType code_blob_type);
  static ReservedCodeSpace reserve_heap_memory(size_t size, size_t rs_ps); // Reserves one continuous chunk of memory for the CodeHeaps

  // Iteration
  static CodeBlob* first_blob(CodeHeap* heap);                // Returns the first CodeBlob on the given CodeHeap
  static CodeBlob* first_blob(CodeBlobType code_blob_type);            // Returns the first CodeBlob of the given type
  static CodeBlob* next_blob(CodeHeap* heap, CodeBlob* cb);   // Returns the next CodeBlob on the given CodeHeap

 private:
  static size_t bytes_allocated_in_freelists();
  static int    allocated_segments();
  static size_t freelists_length();

  // Make private to prevent unsafe calls.  Not all CodeBlob*'s are embedded in a CodeHeap.
  static bool contains(CodeBlob *p) { fatal("don't call me!"); return false; }

 public:
  // Initialization
  static void initialize();
  static size_t page_size(bool aligned = true, size_t min_pages = 1); // Returns the page size used by the CodeCache

  static int code_heap_compare(CodeHeap* const &lhs, CodeHeap* const &rhs);

  static void add_heap(CodeHeap* heap);
  static const GrowableArray<CodeHeap*>* heaps() { return _heaps; }
  static const GrowableArray<CodeHeap*>* compiled_heaps() { return _compiled_heaps; }
  static const GrowableArray<CodeHeap*>* nmethod_heaps() { return _nmethod_heaps; }

  // Allocation/administration
  static CodeBlob* allocate(int size, CodeBlobType code_blob_type, bool handle_alloc_failure = true, CodeBlobType orig_code_blob_type = CodeBlobType::All); // allocates a new CodeBlob
  static void commit(CodeBlob* cb);                        // called when the allocated CodeBlob has been filled
  static int  alignment_unit();                            // guaranteed alignment of all CodeBlobs
  static int  alignment_offset();                          // guaranteed offset of first CodeBlob byte within alignment unit (i.e., allocation header)
  static void free(CodeBlob* cb);                          // frees a CodeBlob
  static void free_unused_tail(CodeBlob* cb, size_t used); // frees the unused tail of a CodeBlob (only used by TemplateInterpreter::initialize())
  static bool contains(void *p);                           // returns whether p is included
  static bool contains(nmethod* nm);                       // returns whether nm is included
  static void blobs_do(void f(CodeBlob* cb));              // iterates over all CodeBlobs
  static void blobs_do(CodeBlobClosure* f);                // iterates over all CodeBlobs
  static void nmethods_do(void f(nmethod* nm));            // iterates over all nmethods
  static void metadata_do(MetadataClosure* f);             // iterates over metadata in alive nmethods

  // Lookup
  static CodeBlob* find_blob(void* start);              // Returns the CodeBlob containing the given address
  static CodeBlob* find_blob_fast(void* start);         // Returns the CodeBlob containing the given address
  static CodeBlob* find_blob_and_oopmap(void* start, int& slot);         // Returns the CodeBlob containing the given address
  static int find_oopmap_slot_fast(void* start);        // Returns a fast oopmap slot if there is any; -1 otherwise
  static nmethod*  find_nmethod(void* start);           // Returns the nmethod containing the given address
  static CompiledMethod* find_compiled(void* start);

  static int       blob_count();                        // Returns the total number of CodeBlobs in the cache
  static int       blob_count(CodeBlobType code_blob_type);
  static int       adapter_count();                     // Returns the total number of Adapters in the cache
  static int       adapter_count(CodeBlobType code_blob_type);
  static int       nmethod_count();                     // Returns the total number of nmethods in the cache
  static int       nmethod_count(CodeBlobType code_blob_type);

  // GC support
  static void verify_oops();

  // Helper scope object managing code cache unlinking behavior, i.e. sets and
  // restores the closure that determines which nmethods are going to be removed
  // during the unlinking part of code cache unloading.
  class UnlinkingScope : StackObj {
    ClosureIsUnloadingBehaviour _is_unloading_behaviour;
    IsUnloadingBehaviour*       _saved_behaviour;

  public:
    UnlinkingScope(BoolObjectClosure* is_alive);
    ~UnlinkingScope();
  };

  // Code cache unloading heuristics
  static uint64_t cold_gc_count();
  static void update_cold_gc_count();
  static void gc_on_allocation();

  // The GC epoch and marking_cycle code below is there to support sweeping
  // nmethods in loom stack chunks.
  static uint64_t gc_epoch();
  static bool is_gc_marking_cycle_active();
  static uint64_t previous_completed_gc_marking_cycle();
  static void on_gc_marking_cycle_start();
  static void on_gc_marking_cycle_finish();
  // Arm nmethods so that special actions are taken (nmethod_entry_barrier) for
  // on-stack nmethods. It's used in two places:
  // 1. Used before the start of concurrent marking so that oops inside
  //    on-stack nmethods are visited.
  // 2. Used at the end of (stw/concurrent) marking so that nmethod::_gc_epoch
  //    is up-to-date, which provides more accurate estimate of
  //    nmethod::is_cold.
  static void arm_all_nmethods();

  static void maybe_restart_compiler(size_t freed_memory);
  static void do_unloading(bool unloading_occurred);
  static uint8_t unloading_cycle() { return _unloading_cycle; }

  static void increment_unloading_cycle();

  static void release_exception_cache(ExceptionCache* entry);
  static void purge_exception_caches();

  // Printing/debugging
  static void print();                           // prints summary
  static void print_internals();
  static void print_memory_overhead();
  static void verify();                          // verifies the code cache
  static void print_trace(const char* event, CodeBlob* cb, int size = 0) PRODUCT_RETURN;
  static void print_summary(outputStream* st, bool detailed = true); // Prints a summary of the code cache usage
  static void log_state(outputStream* st);
  LINUX_ONLY(static void write_perf_map();)
  static const char* get_code_heap_name(CodeBlobType code_blob_type)  { return (heap_available(code_blob_type) ? get_code_heap(code_blob_type)->name() : "Unused"); }
  static void report_codemem_full(CodeBlobType code_blob_type, bool print);

  // Dcmd (Diagnostic commands)
  static void print_codelist(outputStream* st);
  static void print_layout(outputStream* st);

  // The full limits of the codeCache
  static address low_bound()                          { return _low_bound; }
  static address low_bound(CodeBlobType code_blob_type);
  static address high_bound()                         { return _high_bound; }
  static address high_bound(CodeBlobType code_blob_type);

  // Profiling
  static size_t capacity();
  static size_t unallocated_capacity(CodeBlobType code_blob_type);
  static size_t unallocated_capacity();
  static size_t max_capacity();

  static double reverse_free_ratio();

  static size_t max_distance_to_non_nmethod();
  static bool is_non_nmethod(address addr);

  static void clear_inline_caches();                  // clear all inline caches
  static void cleanup_inline_caches_whitebox();       // clean bad nmethods from inline caches

  // Returns true if an own CodeHeap for the given CodeBlobType is available
  static bool heap_available(CodeBlobType code_blob_type);

  // Returns the CodeBlobType for the given CompiledMethod
  static CodeBlobType get_code_blob_type(CompiledMethod* cm) {
    return get_code_heap(cm)->code_blob_type();
  }

  static bool code_blob_type_accepts_compiled(CodeBlobType code_blob_type) {
    bool result = code_blob_type == CodeBlobType::All || code_blob_type <= CodeBlobType::MethodProfiled;
    return result;
  }

  static bool code_blob_type_accepts_nmethod(CodeBlobType type) {
    return type == CodeBlobType::All || type <= CodeBlobType::MethodProfiled;
  }

  static bool code_blob_type_accepts_allocable(CodeBlobType type) {
    return type <= CodeBlobType::All;
  }


  // Returns the CodeBlobType for the given compilation level
  static CodeBlobType get_code_blob_type(int comp_level) {
    if (comp_level == CompLevel_none ||
        comp_level == CompLevel_simple ||
        comp_level == CompLevel_full_optimization) {
      // Non profiled methods
      return CodeBlobType::MethodNonProfiled;
    } else if (comp_level == CompLevel_limited_profile ||
               comp_level == CompLevel_full_profile) {
      // Profiled methods
      return CodeBlobType::MethodProfiled;
    }
    ShouldNotReachHere();
    return static_cast<CodeBlobType>(0);
  }

  static void verify_clean_inline_caches();
  static void verify_icholder_relocations();

  // Deoptimization
 private:
  static void mark_for_deoptimization(DeoptimizationScope* deopt_scope, KlassDepChange& changes);

 public:
  static void mark_all_nmethods_for_deoptimization(DeoptimizationScope* deopt_scope);
  static void mark_for_deoptimization(DeoptimizationScope* deopt_scope, Method* dependee);
  static void make_marked_nmethods_deoptimized();

  // Marks dependents during classloading
  static void mark_dependents_on(DeoptimizationScope* deopt_scope, InstanceKlass* dependee);

  // RedefineClasses support
  // Marks in case of evolution
  static void mark_dependents_for_evol_deoptimization(DeoptimizationScope* deopt_scope);
  static void mark_all_nmethods_for_evol_deoptimization(DeoptimizationScope* deopt_scope);
  static void old_nmethods_do(MetadataClosure* f) NOT_JVMTI_RETURN;
  static void unregister_old_nmethod(CompiledMethod* c) NOT_JVMTI_RETURN;

  // Support for fullspeed debugging
  static void mark_dependents_on_method_for_breakpoint(const methodHandle& dependee);

  // tells if there are nmethods with dependencies
  static bool has_nmethods_with_dependencies();

  static int get_codemem_full_count(CodeBlobType code_blob_type) {
    CodeHeap* heap = get_code_heap(code_blob_type);
    return (heap != nullptr) ? heap->full_count() : 0;
  }

  // CodeHeap State Analytics.
  // interface methods for CodeHeap printing, called by CompileBroker
  static void aggregate(outputStream *out, size_t granularity);
  static void discard(outputStream *out);
  static void print_usedSpace(outputStream *out);
  static void print_freeSpace(outputStream *out);
  static void print_count(outputStream *out);
  static void print_space(outputStream *out);
  static void print_age(outputStream *out);
  static void print_names(outputStream *out);
};


// Iterator to iterate over code blobs in the CodeCache.
// The relaxed iterators only hold the CodeCache_lock across next calls
template <class T, class Filter, bool is_relaxed> class CodeBlobIterator : public StackObj {
 public:
  enum LivenessFilter { all_blobs, only_not_unloading };

 private:
  CodeBlob* _code_blob;   // Current CodeBlob
  GrowableArrayIterator<CodeHeap*> _heap;
  GrowableArrayIterator<CodeHeap*> _end;
  bool _only_not_unloading;

  void initialize_iteration(T* nm) {
  }

  bool next_impl() {
    for (;;) {
      // Walk through heaps as required
      if (!next_blob()) {
        if (_heap == _end) {
          return false;
        }
        ++_heap;
        continue;
      }

      // Filter is_unloading as required
      if (_only_not_unloading) {
        CompiledMethod* cm = _code_blob->as_compiled_method_or_null();
        if (cm != nullptr && cm->is_unloading()) {
          continue;
        }
      }

      return true;
    }
  }

 public:
  CodeBlobIterator(LivenessFilter filter, T* nm = nullptr)
    : _only_not_unloading(filter == only_not_unloading)
  {
    if (Filter::heaps() == nullptr) {
      // The iterator is supposed to shortcut since we have
      // _heap == _end, but make sure we do not have garbage
      // in other fields as well.
      _code_blob = nullptr;
      return;
    }
    _heap = Filter::heaps()->begin();
    _end = Filter::heaps()->end();
    // If set to nullptr, initialized by first call to next()
    _code_blob = nm;
    if (nm != nullptr) {
      while(!(*_heap)->contains(_code_blob)) {
        ++_heap;
      }
      assert((*_heap)->contains(_code_blob), "match not found");
    }
  }

  // Advance iterator to next blob
  bool next() {
    if (is_relaxed) {
      MutexLocker ml(CodeCache_lock, Mutex::_no_safepoint_check_flag);
      return next_impl();
    } else {
      assert_locked_or_safepoint(CodeCache_lock);
      return next_impl();
    }
  }

  bool end()  const { return _code_blob == nullptr; }
  T* method() const { return (T*)_code_blob; }

private:

  // Advance iterator to the next blob in the current code heap
  bool next_blob() {
    if (_heap == _end) {
      return false;
    }
    CodeHeap *heap = *_heap;
    // Get first method CodeBlob
    if (_code_blob == nullptr) {
      _code_blob = CodeCache::first_blob(heap);
      if (_code_blob == nullptr) {
        return false;
      } else if (Filter::apply(_code_blob)) {
        return true;
      }
    }
    // Search for next method CodeBlob
    _code_blob = CodeCache::next_blob(heap, _code_blob);
    while (_code_blob != nullptr && !Filter::apply(_code_blob)) {
      _code_blob = CodeCache::next_blob(heap, _code_blob);
    }
    return _code_blob != nullptr;
  }
};

struct CompiledMethodFilter {
  static bool apply(CodeBlob* cb) { return cb->is_compiled(); }
  static const GrowableArray<CodeHeap*>* heaps() { return CodeCache::compiled_heaps(); }
};


struct NMethodFilter {
  static bool apply(CodeBlob* cb) { return cb->is_nmethod(); }
  static const GrowableArray<CodeHeap*>* heaps() { return CodeCache::nmethod_heaps(); }
};

struct AllCodeBlobsFilter {
  static bool apply(CodeBlob* cb) { return true; }
  static const GrowableArray<CodeHeap*>* heaps() { return CodeCache::heaps(); }
};

typedef CodeBlobIterator<CompiledMethod, CompiledMethodFilter, false /* is_relaxed */> CompiledMethodIterator;
typedef CodeBlobIterator<CompiledMethod, CompiledMethodFilter, true /* is_relaxed */> RelaxedCompiledMethodIterator;
typedef CodeBlobIterator<nmethod, NMethodFilter, false /* is_relaxed */> NMethodIterator;
typedef CodeBlobIterator<CodeBlob, AllCodeBlobsFilter, false /* is_relaxed */> AllCodeBlobsIterator;

#endif // SHARE_CODE_CODECACHE_HPP
