/*
 * Copyright (C) 2013 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_RUNTIME_JDWP_OBJECT_REGISTRY_H_
#define ART_RUNTIME_JDWP_OBJECT_REGISTRY_H_

#include <jni.h>
#include <stdint.h>

#include <map>

#include "base/casts.h"
#include "handle.h"
#include "jdwp/jdwp.h"
#include "obj_ptr.h"
#include "safe_map.h"

namespace art {

namespace mirror {
  class Object;
  class Class;
}  // namespace mirror

struct ObjectRegistryEntry {
  // Is jni_reference a weak global or a regular global reference?
  jobjectRefType jni_reference_type;

  // The reference itself.
  jobject jni_reference;

  // A reference count, so we can implement DisposeObject.
  int32_t reference_count;

  // The corresponding id, so we only need one map lookup in Add.
  JDWP::ObjectId id;

  // The identity hash code of the object. This is the same as the key
  // for object_to_entry_. Store this for DisposeObject().
  int32_t identity_hash_code;
};
std::ostream& operator<<(std::ostream& os, const ObjectRegistryEntry& rhs);

// Tracks those objects currently known to the debugger, so we can use consistent ids when
// referring to them. Normally we keep JNI weak global references to objects, so they can
// still be garbage collected. The debugger can ask us to retain objects, though, so we can
// also promote references to regular JNI global references (and demote them back again if
// the debugger tells us that's okay).
class ObjectRegistry {
 public:
  ObjectRegistry();

  JDWP::ObjectId Add(ObjPtr<mirror::Object> o)
      REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!Locks::thread_list_lock_, !Locks::thread_suspend_count_lock_, !lock_);

  JDWP::RefTypeId AddRefType(ObjPtr<mirror::Class> c)
      REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!Locks::thread_list_lock_, !Locks::thread_suspend_count_lock_, !lock_);

  template<class T>
  JDWP::ObjectId Add(Handle<T> obj_h)
      REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!Locks::thread_list_lock_, !Locks::thread_suspend_count_lock_, !lock_);

  JDWP::RefTypeId AddRefType(Handle<mirror::Class> c_h)
      REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!Locks::thread_list_lock_, !Locks::thread_suspend_count_lock_, !lock_);

  template<typename T> T Get(JDWP::ObjectId id, JDWP::JdwpError* error)
      REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!lock_) {
    if (id == 0) {
      *error = JDWP::ERR_NONE;
      return nullptr;
    }
    return down_cast<T>(InternalGet(id, error));
  }

  void Clear() REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!lock_);

  void DisableCollection(JDWP::ObjectId id)
      REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!lock_);

  void EnableCollection(JDWP::ObjectId id)
      REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!lock_);

  bool IsCollected(JDWP::ObjectId id)
      REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!lock_);

  void DisposeObject(JDWP::ObjectId id, uint32_t reference_count)
      REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!lock_);

  // This is needed to get the jobject instead of the Object*.
  // Avoid using this and use standard Get when possible.
  jobject GetJObject(JDWP::ObjectId id) REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!lock_);

 private:
  template<class T>
  JDWP::ObjectId InternalAdd(Handle<T> obj_h)
      REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!lock_, !Locks::thread_list_lock_, !Locks::thread_suspend_count_lock_);

  mirror::Object* InternalGet(JDWP::ObjectId id, JDWP::JdwpError* error)
      REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!lock_);

  void Demote(ObjectRegistryEntry& entry)
      REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(lock_);

  void Promote(ObjectRegistryEntry& entry)
      REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(lock_);

  bool ContainsLocked(Thread* self,
                      ObjPtr<mirror::Object> o,
                      int32_t identity_hash_code,
                      ObjectRegistryEntry** out_entry)
      REQUIRES(lock_) REQUIRES_SHARED(Locks::mutator_lock_);

  Mutex lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
  std::multimap<int32_t, ObjectRegistryEntry*> object_to_entry_ GUARDED_BY(lock_);
  SafeMap<JDWP::ObjectId, ObjectRegistryEntry*> id_to_entry_ GUARDED_BY(lock_);

  size_t next_id_ GUARDED_BY(lock_);
};

}  // namespace art

#endif  // ART_RUNTIME_JDWP_OBJECT_REGISTRY_H_
