/*
 * Copyright (C) 2011 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_ART_FIELD_H_
#define ART_RUNTIME_ART_FIELD_H_

#include <jni.h>

#include "gc_root.h"
#include "modifiers.h"
#include "object_callbacks.h"
#include "offsets.h"
#include "primitive.h"
#include "read_barrier_option.h"

namespace art {

class DexFile;
class ScopedObjectAccessAlreadyRunnable;

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

class ArtField {
 public:
  ArtField();

  mirror::Class* GetDeclaringClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);

  void SetDeclaringClass(mirror::Class *new_declaring_class)
      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);

  uint32_t GetAccessFlags() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);

  void SetAccessFlags(uint32_t new_access_flags) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    // Not called within a transaction.
    access_flags_ = new_access_flags;
  }

  bool IsPublic() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    return (GetAccessFlags() & kAccPublic) != 0;
  }

  bool IsStatic() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    return (GetAccessFlags() & kAccStatic) != 0;
  }

  bool IsFinal() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    return (GetAccessFlags() & kAccFinal) != 0;
  }

  uint32_t GetDexFieldIndex() {
    return field_dex_idx_;
  }

  void SetDexFieldIndex(uint32_t new_idx) {
    // Not called within a transaction.
    field_dex_idx_ = new_idx;
  }

  // Offset to field within an Object.
  MemberOffset GetOffset() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);

  static MemberOffset OffsetOffset() {
    return MemberOffset(OFFSETOF_MEMBER(ArtField, offset_));
  }

  MemberOffset GetOffsetDuringLinking() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);

  void SetOffset(MemberOffset num_bytes) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);

  // field access, null object for static fields
  uint8_t GetBoolean(mirror::Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);

  template<bool kTransactionActive>
  void SetBoolean(mirror::Object* object, uint8_t z) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);

  int8_t GetByte(mirror::Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);

  template<bool kTransactionActive>
  void SetByte(mirror::Object* object, int8_t b) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);

  uint16_t GetChar(mirror::Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);

  template<bool kTransactionActive>
  void SetChar(mirror::Object* object, uint16_t c) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);

  int16_t GetShort(mirror::Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);

  template<bool kTransactionActive>
  void SetShort(mirror::Object* object, int16_t s) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);

  int32_t GetInt(mirror::Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);

  template<bool kTransactionActive>
  void SetInt(mirror::Object* object, int32_t i) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);

  int64_t GetLong(mirror::Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);

  template<bool kTransactionActive>
  void SetLong(mirror::Object* object, int64_t j) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);

  float GetFloat(mirror::Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);

  template<bool kTransactionActive>
  void SetFloat(mirror::Object* object, float f) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);

  double GetDouble(mirror::Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);

  template<bool kTransactionActive>
  void SetDouble(mirror::Object* object, double d) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);

  mirror::Object* GetObject(mirror::Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);

  template<bool kTransactionActive>
  void SetObject(mirror::Object* object, mirror::Object* l)
      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);

  // Raw field accesses.
  uint32_t Get32(mirror::Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);

  template<bool kTransactionActive>
  void Set32(mirror::Object* object, uint32_t new_value)
      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);

  uint64_t Get64(mirror::Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);

  template<bool kTransactionActive>
  void Set64(mirror::Object* object, uint64_t new_value) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);

  mirror::Object* GetObj(mirror::Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);

  template<bool kTransactionActive>
  void SetObj(mirror::Object* object, mirror::Object* new_value)
      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);

  void VisitRoots(RootVisitor* visitor)
      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);

  bool IsVolatile() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    return (GetAccessFlags() & kAccVolatile) != 0;
  }

  // Returns an instance field with this offset in the given class or null if not found.
  static ArtField* FindInstanceFieldWithOffset(mirror::Class* klass, uint32_t field_offset)
      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);

  const char* GetName() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);

  // Resolves / returns the name from the dex cache.
  mirror::String* GetStringName(Thread* self, bool resolve)
      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);

  const char* GetTypeDescriptor() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);

  Primitive::Type GetTypeAsPrimitiveType() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);

  bool IsPrimitiveType() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);

  template <bool kResolve>
  mirror::Class* GetType() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);

  size_t FieldSize() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);

  mirror::DexCache* GetDexCache() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);

  const DexFile* GetDexFile() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);

  GcRoot<mirror::Class>& DeclaringClassRoot() {
    return declaring_class_;
  }

 private:
  mirror::Class* ProxyFindSystemClass(const char* descriptor)
      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
  mirror::Class* ResolveGetType(uint32_t type_idx) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
  mirror::String* ResolveGetStringName(Thread* self, const DexFile& dex_file, uint32_t string_idx,
                                       mirror::DexCache* dex_cache)
      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);

  GcRoot<mirror::Class> declaring_class_;

  uint32_t access_flags_;

  // Dex cache index of field id
  uint32_t field_dex_idx_;

  // Offset of field within an instance or in the Class' static fields
  uint32_t offset_;
};

}  // namespace art

#endif  // ART_RUNTIME_ART_FIELD_H_
