/*
 * Copyright (c) 2012, 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_VM_SERVICES_MEM_RECORDER_HPP
#define SHARE_VM_SERVICES_MEM_RECORDER_HPP

#include "memory/allocation.hpp"
#include "runtime/os.hpp"
#include "services/memPtrArray.hpp"

class MemSnapshot;
class MemTracker;
class MemTrackWorker;

// Fixed size memory pointer array implementation
template <class E, int SIZE> class FixedSizeMemPointerArray :
  public MemPointerArray {
  // This implementation is for memory recorder only
  friend class MemRecorder;

 private:
  E      _data[SIZE];
  int    _size;

 protected:
  FixedSizeMemPointerArray(bool init_elements = false):
   _size(0){
    if (init_elements) {
      for (int index = 0; index < SIZE; index ++) {
        ::new ((void*)&_data[index]) E();
      }
    }
  }

  void* operator new(size_t size, const std::nothrow_t& nothrow_constant) {
    // the instance is part of memRecorder, needs to be tagged with 'otNMTRecorder'
    // to avoid recursion
    return os::malloc(size, (mtNMT | otNMTRecorder));
  }

  void* operator new(size_t size) {
    assert(false, "use nothrow version");
    return NULL;
  }

  void operator delete(void* p) {
    os::free(p, (mtNMT | otNMTRecorder));
  }

  // instance size
  inline size_t instance_size() const {
    return sizeof(FixedSizeMemPointerArray<E, SIZE>);
  }

  NOT_PRODUCT(int capacity() const { return SIZE; })

 public:
  // implementation of public interface
  bool out_of_memory() const { return false; }
  bool is_empty()      const { return _size == 0; }
  bool is_full()             { return length() >= SIZE; }
  int  length()        const { return _size; }

  void clear() {
    _size = 0;
  }

  bool append(MemPointer* ptr) {
    if (is_full()) return false;
    _data[_size ++] = *(E*)ptr;
    return true;
  }

  virtual bool insert_at(MemPointer* p, int pos) {
    assert(false, "append only");
    return false;
  }

  virtual bool remove_at(int pos) {
    assert(false, "not supported");
    return false;
  }

  MemPointer* at(int index) const {
    assert(index >= 0 && index < length(),
      "parameter check");
    return ((E*)&_data[index]);
  }

  void sort(FN_SORT fn) {
    qsort((void*)_data, _size, sizeof(E), fn);
  }

  bool shrink() {
    return false;
  }
};


// This iterator requires pre-sorted MemPointerArray, which is sorted by:
//  1. address
//  2. allocation type
//  3. sequence number
// During the array walking, iterator collapses pointers with the same
// address and allocation type, and only returns the one with highest
// sequence number.
//
// This is read-only iterator, update methods are asserted.
class SequencedRecordIterator : public MemPointerArrayIterator {
 private:
   MemPointerArrayIteratorImpl _itr;
   MemPointer*                 _cur;

 public:
  SequencedRecordIterator(const MemPointerArray* arr):
    _itr(const_cast<MemPointerArray*>(arr)) {
    _cur = next_record();
  }

  SequencedRecordIterator(const SequencedRecordIterator& itr):
    _itr(itr._itr) {
    _cur = next_record();
  }

  // return the pointer at current position
  virtual MemPointer* current() const {
    return _cur;
  };

  // return the next pointer and advance current position
  virtual MemPointer* next() {
    _cur = next_record();
    return _cur;
  }

  // return the next pointer without advancing current position
  virtual MemPointer* peek_next() const {
    assert(false, "not implemented");
    return NULL;

  }
  // return the previous pointer without changing current position
  virtual MemPointer* peek_prev() const {
    assert(false, "not implemented");
    return NULL;
  }

  // remove the pointer at current position
  virtual void remove() {
    assert(false, "read-only iterator");
  };
  // insert the pointer at current position
  virtual bool insert(MemPointer* ptr) {
    assert(false, "read-only iterator");
    return false;
  }

  virtual bool insert_after(MemPointer* ptr) {
    assert(false, "read-only iterator");
    return false;
  }
 private:
  // collapse the 'same kind' of records, and return this 'kind' of
  // record with highest sequence number
  MemPointer* next_record();

  // Test if the two records are the same kind: the same memory block and allocation
  // type.
  inline bool same_kind(const MemPointerRecord* p1, const MemPointerRecord* p2) const {
    assert(!p1->is_vm_pointer() && !p2->is_vm_pointer(), "malloc pointer only");
    return (p1->addr() == p2->addr() &&
      (p1->flags() &MemPointerRecord::tag_masks) ==
      (p2->flags() & MemPointerRecord::tag_masks));
  }
};



#define DEFAULT_RECORDER_PTR_ARRAY_SIZE 512

class MemRecorder : public CHeapObj<mtNMT|otNMTRecorder> {
  friend class MemSnapshot;
  friend class MemTracker;
  friend class MemTrackWorker;
  friend class GenerationData;

 protected:
  // the array that holds memory records
  MemPointerArray*         _pointer_records;

 private:
  // used for linked list
  MemRecorder*             _next;
  // active recorder can only record a certain generation data
  debug_only(unsigned long _generation;)

 protected:
  _NOINLINE_ MemRecorder();
  ~MemRecorder();

  // record a memory operation
  bool record(address addr, MEMFLAGS flags, size_t size, address caller_pc = 0);

  // linked list support
  inline void set_next(MemRecorder* rec) {
    _next = rec;
  }

  inline MemRecorder* next() const {
    return _next;
  }

  // if the recorder is full
  inline bool is_full() const {
    assert(_pointer_records != NULL, "just check");
    return _pointer_records->is_full();
  }

  // if running out of memory when initializing recorder's internal
  // data
  inline bool out_of_memory() const {
    return (_pointer_records == NULL ||
      _pointer_records->out_of_memory());
  }

  inline void clear() {
    assert(_pointer_records != NULL, "Just check");
    _pointer_records->clear();
  }

  SequencedRecordIterator pointer_itr();

 protected:
  // number of MemRecorder instance
  static volatile jint _instance_count;

 private:
  // sorting function, sort records into following order
  // 1. memory address
  // 2. allocation type
  // 3. sequence number
  static int sort_record_fn(const void* e1, const void* e2);

  debug_only(void check_dup_seq(jint seq) const;)
  debug_only(void set_generation();)
};

#endif // SHARE_VM_SERVICES_MEM_RECORDER_HPP
