/*
 * Copyright (C) 2017 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_VAR_HANDLE_H_
#define ART_RUNTIME_MIRROR_VAR_HANDLE_H_

#include "handle.h"
#include "interpreter/shadow_frame.h"
#include "jvalue.h"
#include "object.h"

namespace art {

template<class T> class Handle;
class InstructionOperands;
template<class T> class ObjPtr;

enum class Intrinsics;

struct VarHandleOffsets;
struct FieldVarHandleOffsets;
struct ArrayElementVarHandleOffsets;
struct ByteArrayViewVarHandleOffsets;
struct ByteBufferViewVarHandleOffsets;

class ShadowFrameGetter;

namespace mirror {

class MethodType;
class VarHandleTest;

// C++ mirror of java.lang.invoke.VarHandle
class MANAGED VarHandle : public Object {
 public:
  // The maximum number of parameters a VarHandle accessor method can
  // take. The Worst case is equivalent to a compare-and-swap
  // operation on an array element which requires four parameters
  // (array, index, old, new).
  static constexpr int kMaxAccessorParameters = 4;

  // The maximum number of VarType parameters a VarHandle accessor
  // method can take.
  static constexpr size_t kMaxVarTypeParameters = 2;

  // Enumeration of the possible access modes. This mirrors the enum
  // in java.lang.invoke.VarHandle.
  enum class AccessMode : uint32_t {
    kGet,
    kSet,
    kGetVolatile,
    kSetVolatile,
    kGetAcquire,
    kSetRelease,
    kGetOpaque,
    kSetOpaque,
    kCompareAndSet,
    kCompareAndExchange,
    kCompareAndExchangeAcquire,
    kCompareAndExchangeRelease,
    kWeakCompareAndSetPlain,
    kWeakCompareAndSet,
    kWeakCompareAndSetAcquire,
    kWeakCompareAndSetRelease,
    kGetAndSet,
    kGetAndSetAcquire,
    kGetAndSetRelease,
    kGetAndAdd,
    kGetAndAddAcquire,
    kGetAndAddRelease,
    kGetAndBitwiseOr,
    kGetAndBitwiseOrRelease,
    kGetAndBitwiseOrAcquire,
    kGetAndBitwiseAnd,
    kGetAndBitwiseAndRelease,
    kGetAndBitwiseAndAcquire,
    kGetAndBitwiseXor,
    kGetAndBitwiseXorRelease,
    kGetAndBitwiseXorAcquire,
    kLast = kGetAndBitwiseXorAcquire,
  };
  constexpr static size_t kNumberOfAccessModes = static_cast<size_t>(AccessMode::kLast) + 1u;

  // Returns true if the AccessMode specified is a supported operation.
  bool IsAccessModeSupported(AccessMode accessMode) REQUIRES_SHARED(Locks::mutator_lock_) {
    return (GetAccessModesBitMask() & (1u << static_cast<uint32_t>(accessMode))) != 0;
  }

  enum MatchKind : uint8_t {
    kNone,
    kWithConversions,
    kExact
  };

  // Returns match information on the compatability between the exact method type for
  // 'access_mode' and the provided 'method_type'.
  MatchKind GetMethodTypeMatchForAccessMode(AccessMode access_mode, ObjPtr<MethodType> method_type)
        REQUIRES_SHARED(Locks::mutator_lock_);

  // Returns true if the MethodType specified is compatible with the
  // specified access_mode if the first parameter of method_type is
  // ignored. This is useful for comparing MethodType instances when
  // invoking a VarHandleAccessor via a MethodHandle invoker.
  bool IsInvokerMethodTypeCompatible(AccessMode access_mode, ObjPtr<MethodType> method_type)
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Allocates and returns the MethodType associated with the
  // AccessMode. No check is made for whether the AccessMode is a
  // supported operation so the MethodType can be used when raising a
  // WrongMethodTypeException exception.
  ObjPtr<MethodType> GetMethodTypeForAccessMode(Thread* self, AccessMode accessMode)
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Returns a string representing the descriptor of the MethodType associated with
  // this AccessMode.
  std::string PrettyDescriptorForAccessMode(AccessMode access_mode)
      REQUIRES_SHARED(Locks::mutator_lock_);

  bool Access(AccessMode access_mode,
              ShadowFrame* shadow_frame,
              const InstructionOperands* const operands,
              JValue* result)
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Gets the variable type that is operated on by this VarHandle instance.
  ObjPtr<Class> GetVarType() REQUIRES_SHARED(Locks::mutator_lock_);

  // Gets the return type descriptor for a named accessor method,
  // nullptr if accessor_method is not supported.
  static const char* GetReturnTypeDescriptor(const char* accessor_method);

  // Returns the AccessMode corresponding to a VarHandle accessor intrinsic.
  static AccessMode GetAccessModeByIntrinsic(Intrinsics ordinal);

  // Returns true and sets access_mode if method_name corresponds to a
  // VarHandle access method, such as "setOpaque". Returns false otherwise.
  static bool GetAccessModeByMethodName(const char* method_name, AccessMode* access_mode);

 private:
  ObjPtr<Class> GetCoordinateType0() REQUIRES_SHARED(Locks::mutator_lock_);
  ObjPtr<Class> GetCoordinateType1() REQUIRES_SHARED(Locks::mutator_lock_);
  int32_t GetAccessModesBitMask() REQUIRES_SHARED(Locks::mutator_lock_);

  static ObjPtr<MethodType> GetMethodTypeForAccessMode(Thread* self,
                                                       ObjPtr<VarHandle> var_handle,
                                                       AccessMode access_mode)
      REQUIRES_SHARED(Locks::mutator_lock_);

  static MemberOffset VarTypeOffset() {
    return MemberOffset(OFFSETOF_MEMBER(VarHandle, var_type_));
  }

  static MemberOffset CoordinateType0Offset() {
    return MemberOffset(OFFSETOF_MEMBER(VarHandle, coordinate_type0_));
  }

  static MemberOffset CoordinateType1Offset() {
    return MemberOffset(OFFSETOF_MEMBER(VarHandle, coordinate_type1_));
  }

  static MemberOffset AccessModesBitMaskOffset() {
    return MemberOffset(OFFSETOF_MEMBER(VarHandle, access_modes_bit_mask_));
  }

  HeapReference<mirror::Class> coordinate_type0_;
  HeapReference<mirror::Class> coordinate_type1_;
  HeapReference<mirror::Class> var_type_;
  int32_t access_modes_bit_mask_;

  friend class VarHandleTest;  // for testing purposes
  friend struct art::VarHandleOffsets;  // for verifying offset information
  DISALLOW_IMPLICIT_CONSTRUCTORS(VarHandle);
};

// Represents a VarHandle to a static or instance field.
// The corresponding managed class in libart java.lang.invoke.FieldVarHandle.
class MANAGED FieldVarHandle : public VarHandle {
 public:
  bool Access(AccessMode access_mode,
              ShadowFrame* shadow_frame,
              const InstructionOperands* const operands,
              JValue* result)
      REQUIRES_SHARED(Locks::mutator_lock_);

  ArtField* GetField() REQUIRES_SHARED(Locks::mutator_lock_);

  // Used for updating var-handles to obsolete fields.
  template<typename Visitor>
  inline void VisitTarget(Visitor&& v) REQUIRES(Locks::mutator_lock_);

 private:
  static MemberOffset ArtFieldOffset() {
    return MemberOffset(OFFSETOF_MEMBER(FieldVarHandle, art_field_));
  }

  // ArtField instance corresponding to variable for accessors.
  int64_t art_field_;

  friend class VarHandleTest;  // for var_handle_test.
  friend struct art::FieldVarHandleOffsets;  // for verifying offset information
  DISALLOW_IMPLICIT_CONSTRUCTORS(FieldVarHandle);
};

// Represents a VarHandle providing accessors to an array.
// The corresponding managed class in libart java.lang.invoke.ArrayElementVarHandle.
class MANAGED ArrayElementVarHandle : public VarHandle {
 public:
    bool Access(AccessMode access_mode,
                ShadowFrame* shadow_frame,
                const InstructionOperands* const operands,
                JValue* result)
      REQUIRES_SHARED(Locks::mutator_lock_);

 private:
  friend class VarHandleTest;
  DISALLOW_IMPLICIT_CONSTRUCTORS(ArrayElementVarHandle);
};

// Represents a VarHandle providing accessors to a view of a ByteArray.
// The corresponding managed class in libart java.lang.invoke.ByteArrayViewVarHandle.
class MANAGED ByteArrayViewVarHandle : public VarHandle {
 public:
  bool Access(AccessMode access_mode,
              ShadowFrame* shadow_frame,
              const InstructionOperands* const operands,
              JValue* result)
      REQUIRES_SHARED(Locks::mutator_lock_);

  bool GetNativeByteOrder() REQUIRES_SHARED(Locks::mutator_lock_);

 private:
  static MemberOffset NativeByteOrderOffset() {
    return MemberOffset(OFFSETOF_MEMBER(ByteArrayViewVarHandle, native_byte_order_));
  }

  // Flag indicating that accessors should use native byte-ordering.
  uint8_t native_byte_order_;

  friend class VarHandleTest;  // for var_handle_test.
  friend struct art::ByteArrayViewVarHandleOffsets;  // for verifying offset information
  DISALLOW_IMPLICIT_CONSTRUCTORS(ByteArrayViewVarHandle);
};

// Represents a VarHandle providing accessors to a view of a ByteBuffer
// The corresponding managed class in libart java.lang.invoke.ByteBufferViewVarHandle.
class MANAGED ByteBufferViewVarHandle : public VarHandle {
 public:
  bool Access(AccessMode access_mode,
              ShadowFrame* shadow_frame,
              const InstructionOperands* const operands,
              JValue* result)
      REQUIRES_SHARED(Locks::mutator_lock_);

  bool GetNativeByteOrder() REQUIRES_SHARED(Locks::mutator_lock_);

 private:
  bool AccessHeapBuffer(AccessMode access_mode,
                        ObjPtr<Object> byte_buffer,
                        int buffer_offset,
                        ObjPtr<ByteArray> heap_byte_array,
                        ShadowFrameGetter* getter,
                        JValue* result)
      REQUIRES_SHARED(Locks::mutator_lock_);

  bool AccessFixedMemory(AccessMode access_mode,
                         ObjPtr<Object> byte_buffer,
                         int buffer_offset,
                         ShadowFrameGetter* getter,
                         JValue* result)
      REQUIRES_SHARED(Locks::mutator_lock_);

  static MemberOffset NativeByteOrderOffset() {
    return MemberOffset(OFFSETOF_MEMBER(ByteBufferViewVarHandle, native_byte_order_));
  }

  // Flag indicating that accessors should use native byte-ordering.
  uint8_t native_byte_order_;

  friend class VarHandleTest;  // for var_handle_test.
  friend struct art::ByteBufferViewVarHandleOffsets;  // for verifying offset information
  DISALLOW_IMPLICIT_CONSTRUCTORS(ByteBufferViewVarHandle);
};

}  // namespace mirror
}  // namespace art

#endif  // ART_RUNTIME_MIRROR_VAR_HANDLE_H_
