/*
 * Copyright (C) 2014 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_MIRROR_OBJECT_REFERENCE_H_
#define ART_RUNTIME_MIRROR_OBJECT_REFERENCE_H_

#include "base/atomic.h"
#include "base/locks.h"  // For Locks::mutator_lock_.
#include "heap_poisoning.h"
#include "obj_ptr.h"
#include "runtime_globals.h"

namespace art {
namespace mirror {

class Object;

// Classes shared with the managed side of the world need to be packed so that they don't have
// extra platform specific padding.
#define MANAGED PACKED(4)

template<bool kPoisonReferences, class MirrorType>
class PtrCompression {
 public:
  // Compress reference to its bit representation.
  static uint32_t Compress(MirrorType* mirror_ptr) {
    uintptr_t as_bits = reinterpret_cast<uintptr_t>(mirror_ptr);
    return static_cast<uint32_t>(kPoisonReferences ? -as_bits : as_bits);
  }

  // Uncompress an encoded reference from its bit representation.
  static MirrorType* Decompress(uint32_t ref) {
    uintptr_t as_bits = kPoisonReferences ? -ref : ref;
    return reinterpret_cast<MirrorType*>(as_bits);
  }

  // Convert an ObjPtr to a compressed reference.
  static uint32_t Compress(ObjPtr<MirrorType> ptr) REQUIRES_SHARED(Locks::mutator_lock_);
};

// Value type representing a reference to a mirror::Object of type MirrorType.
template<bool kPoisonReferences, class MirrorType>
class MANAGED ObjectReference {
 private:
  using Compression = PtrCompression<kPoisonReferences, MirrorType>;

 public:
  /*
   * Returns a pointer to the mirror of the managed object this reference is for.
   *
   * This does NOT return the current object (which isn't derived from, and
   * therefor cannot be a mirror::Object) as a mirror pointer.  Instead, this
   * returns a pointer to the mirror of the managed object this refers to.
   *
   * TODO (chriswailes): Rename to GetPtr().
   */
  MirrorType* AsMirrorPtr() const {
    return Compression::Decompress(reference_);
  }

  void Assign(MirrorType* other) {
    reference_ = Compression::Compress(other);
  }

  void Assign(ObjPtr<MirrorType> ptr) REQUIRES_SHARED(Locks::mutator_lock_);

  void Clear() {
    reference_ = 0;
    DCHECK(IsNull());
  }

  bool IsNull() const {
    return reference_ == 0;
  }

  uint32_t AsVRegValue() const {
    return reference_;
  }

  static ObjectReference<kPoisonReferences, MirrorType> FromMirrorPtr(MirrorType* mirror_ptr)
      REQUIRES_SHARED(Locks::mutator_lock_) {
    return ObjectReference<kPoisonReferences, MirrorType>(mirror_ptr);
  }

 protected:
  explicit ObjectReference(MirrorType* mirror_ptr) REQUIRES_SHARED(Locks::mutator_lock_)
      : reference_(Compression::Compress(mirror_ptr)) {
  }

  // The encoded reference to a mirror::Object.
  uint32_t reference_;
};

// References between objects within the managed heap.
// Similar API to ObjectReference, but not a value type. Supports atomic access.
template<class MirrorType>
class MANAGED HeapReference {
 private:
  using Compression = PtrCompression<kPoisonHeapReferences, MirrorType>;

 public:
  HeapReference() REQUIRES_SHARED(Locks::mutator_lock_) : HeapReference(nullptr) {}

  template <bool kIsVolatile = false>
  MirrorType* AsMirrorPtr() const REQUIRES_SHARED(Locks::mutator_lock_) {
    return Compression::Decompress(
        kIsVolatile ? reference_.load(std::memory_order_seq_cst) : reference_.LoadJavaData());
  }

  template <bool kIsVolatile = false>
  void Assign(MirrorType* other) REQUIRES_SHARED(Locks::mutator_lock_) {
    if (kIsVolatile) {
      reference_.store(Compression::Compress(other), std::memory_order_seq_cst);
    } else {
      reference_.StoreJavaData(Compression::Compress(other));
    }
  }

  template <bool kIsVolatile = false>
  void Assign(ObjPtr<MirrorType> ptr) REQUIRES_SHARED(Locks::mutator_lock_);

  void Clear() {
    reference_.StoreJavaData(0);
    DCHECK(IsNull());
  }

  bool IsNull() const {
    return reference_.LoadJavaData() == 0;
  }

  static HeapReference<MirrorType> FromMirrorPtr(MirrorType* mirror_ptr)
      REQUIRES_SHARED(Locks::mutator_lock_) {
    return HeapReference<MirrorType>(mirror_ptr);
  }

  bool CasWeakRelaxed(MirrorType* old_ptr, MirrorType* new_ptr)
      REQUIRES_SHARED(Locks::mutator_lock_);

 private:
  explicit HeapReference(MirrorType* mirror_ptr) REQUIRES_SHARED(Locks::mutator_lock_)
      : reference_(Compression::Compress(mirror_ptr)) {}

  // The encoded reference to a mirror::Object. Atomically updateable.
  Atomic<uint32_t> reference_;
};

static_assert(sizeof(mirror::HeapReference<mirror::Object>) == kHeapReferenceSize,
              "heap reference size does not match");

// Standard compressed reference used in the runtime. Used for StackReference and GC roots.
template<class MirrorType>
class MANAGED CompressedReference : public mirror::ObjectReference<false, MirrorType> {
 public:
  CompressedReference<MirrorType>() REQUIRES_SHARED(Locks::mutator_lock_)
      : mirror::ObjectReference<false, MirrorType>(nullptr) {}

  static CompressedReference<MirrorType> FromMirrorPtr(MirrorType* p)
      REQUIRES_SHARED(Locks::mutator_lock_) {
    return CompressedReference<MirrorType>(p);
  }

 private:
  explicit CompressedReference(MirrorType* p) REQUIRES_SHARED(Locks::mutator_lock_)
      : mirror::ObjectReference<false, MirrorType>(p) {}
};

}  // namespace mirror
}  // namespace art

#endif  // ART_RUNTIME_MIRROR_OBJECT_REFERENCE_H_
