/*
 * Copyright (c) 1997, 2024, 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_INTERPRETER_OOPMAPCACHE_HPP
#define SHARE_INTERPRETER_OOPMAPCACHE_HPP

#include "runtime/handles.hpp"
#include "runtime/mutex.hpp"
#include "utilities/globalDefinitions.hpp"

// A Cache for storing (method, bci) -> oopMap.
// The memory management system uses the cache when locating object
// references in an interpreted frame.
//
// OopMapCache's are allocated lazily per InstanceKlass.

// The oopMap (InterpreterOopMap) is stored as a bit mask. If the
// bit_mask can fit into four words it is stored in
// the _bit_mask array, otherwise it is allocated on the heap.
// For OopMapCacheEntry the bit_mask is allocated in the C heap
// because these entries persist between garbage collections.
// For InterpreterOopMap the bit_mask is allocated in the C heap
// to avoid issues with allocations from the resource area that have
// to live accross the oop closure. InterpreterOopMap should only be
// created and deleted during the same garbage collection.
//
// If ENABBLE_ZAP_DEAD_LOCALS is defined, two bits are used
// per entry instead of one. In all cases,
// the first bit is set to indicate oops as opposed to other
// values. If the second bit is available,
// it is set for dead values. We get the following encoding:
//
// 00 live value
// 01 live oop
// 10 dead value
// 11 <unused>                                   (we cannot distinguish between dead oops or values with the current oop map generator)


class OffsetClosure  {
 public:
  virtual void offset_do(int offset) = 0;
};

class Method;
class OopMapCacheEntry;

class InterpreterOopMap: ResourceObj {
  friend class OopMapCache;

 public:
  enum {
    N                = 4,                // the number of words reserved
                                         // for inlined mask storage
    small_mask_limit = N * BitsPerWord,  // the maximum number of bits
                                         // available for small masks,
                                         // small_mask_limit can be set to 0
                                         // for testing bit_mask allocation

    bits_per_entry   = 2,
    dead_bit_number  = 1,
    oop_bit_number   = 0
  };

 private:
  Method*        _method;         // the method for which the mask is valid
  int            _mask_size;      // the mask size in bits (USHRT_MAX if invalid)
  int            _expression_stack_size; // the size of the expression stack in slots
  unsigned short _bci;            // the bci    for which the mask is valid

 protected:
  int            _num_oops;
  intptr_t       _bit_mask[N];    // the bit mask if
                                  // mask_size <= small_mask_limit,
                                  // ptr to bit mask otherwise
                                  // "protected" so that sub classes can
                                  // access it without using trickery in
                                  // method bit_mask().

  // access methods
  Method*        method() const                  { return _method; }
  void           set_method(Method* v)           { _method = v; }
  unsigned short bci() const                     { return _bci; }
  void           set_bci(unsigned short v)       { _bci = v; }
  int            mask_size() const               { return _mask_size; }
  void           set_mask_size(int v)            { _mask_size = v; }
  // Test bit mask size and return either the in-line bit mask or allocated
  // bit mask.
  uintptr_t*  bit_mask() const                   { return (uintptr_t*)(mask_size() <= small_mask_limit ? (intptr_t)_bit_mask : _bit_mask[0]); }

  // return the word size of_bit_mask.  mask_size() <= 4 * MAX_USHORT
  size_t mask_word_size() const {
    return (mask_size() + BitsPerWord - 1) / BitsPerWord;
  }

  uintptr_t entry_at(int offset) const           { int i = offset * bits_per_entry; return bit_mask()[i / BitsPerWord] >> (i % BitsPerWord); }

  void set_expression_stack_size(int sz)         { _expression_stack_size = sz; }

  // Lookup
  bool match(const methodHandle& method, int bci) const { return _method == method() && _bci == bci; }
  bool is_empty() const;

  // Initialization
  void initialize();

 public:
  InterpreterOopMap();
  ~InterpreterOopMap();

  // Copy the OopMapCacheEntry in parameter "src" into this
  // InterpreterOopMap.  If the _bit_mask[0] in "src" points to
  // allocated space (i.e., the bit mask was too large to hold
  // in-line), allocate the space from the C heap.
  void copy_from(const OopMapCacheEntry* src);

  void iterate_oop(OffsetClosure* oop_closure) const;
  void print() const;

  int number_of_entries() const                  { return mask_size() / bits_per_entry; }
  bool is_dead(int offset) const                 { return (entry_at(offset) & (1 << dead_bit_number)) != 0; }
  bool is_oop (int offset) const                 { return (entry_at(offset) & (1 << oop_bit_number )) != 0; }
  int  num_oops() const                          { return _num_oops; }

  int expression_stack_size() const              { return _expression_stack_size; }

  // Determines if a valid mask has been computed
  bool has_valid_mask() const { return _mask_size != USHRT_MAX; }
};

class OopMapCache : public CHeapObj<mtClass> {
 static OopMapCacheEntry* volatile _old_entries;
 private:
  static constexpr int size = 32;        // Use fixed size for now
  static constexpr int probe_depth = 3;  // probe depth in case of collisions

  OopMapCacheEntry* volatile _array[size];

  unsigned int hash_value_for(const methodHandle& method, int bci) const;
  OopMapCacheEntry* entry_at(int i) const;
  bool put_at(int i, OopMapCacheEntry* entry, OopMapCacheEntry* old);

  static void enqueue_for_cleanup(OopMapCacheEntry* entry);

  void flush();

 public:
  OopMapCache();
  ~OopMapCache();                                // free up memory

  // flush cache entry is occupied by an obsolete method
  void flush_obsolete_entries();

  // Returns the oopMap for (method, bci) in parameter "entry".
  // Returns false if an oop map was not found.
  void lookup(const methodHandle& method, int bci, InterpreterOopMap* entry);

  // Compute an oop map without updating the cache or grabbing any locks (for debugging)
  static void compute_one_oop_map(const methodHandle& method, int bci, InterpreterOopMap* entry);

  // Check if we need to clean up old entries
  static bool has_cleanup_work();

  // Request cleanup if work is needed and notification is currently possible
  static void try_trigger_cleanup();

  // Clean up the old entries
  static void cleanup();
};

#endif // SHARE_INTERPRETER_OOPMAPCACHE_HPP
