/*
 * Copyright (C) 2008 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.
 */

#include "java_lang_reflect_Field.h"

#include "android-base/stringprintf.h"
#include "nativehelper/jni_macros.h"

#include "art_field-inl.h"
#include "base/utils.h"
#include "class_linker-inl.h"
#include "class_linker.h"
#include "common_throws.h"
#include "dex/dex_file-inl.h"
#include "dex/dex_file_annotations.h"
#include "gc/reference_processor.h"
#include "jni/jni_internal.h"
#include "jvalue-inl.h"
#include "mirror/class-inl.h"
#include "mirror/field-inl.h"
#include "mirror/object_array-alloc-inl.h"
#include "native_util.h"
#include "reflection-inl.h"
#include "scoped_fast_native_object_access-inl.h"
#include "well_known_classes.h"

namespace art HIDDEN {

using android::base::StringPrintf;

template<bool kIsSet>
ALWAYS_INLINE inline static bool VerifyFieldAccess(Thread* self,
                                                   ObjPtr<mirror::Field> field,
                                                   ObjPtr<mirror::Object> obj)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  if (kIsSet && field->IsFinal()) {
    ThrowIllegalAccessException(
            StringPrintf("Cannot set %s field %s of class %s",
                PrettyJavaAccessFlags(field->GetAccessFlags()).c_str(),
                ArtField::PrettyField(field->GetArtField()).c_str(),
                field->GetDeclaringClass() == nullptr ? "null" :
                    field->GetDeclaringClass()->PrettyClass().c_str()).c_str());
    return false;
  }
  ObjPtr<mirror::Class> calling_class;
  if (!VerifyAccess(self,
                    obj,
                    field->GetDeclaringClass(),
                    field->GetAccessFlags(),
                    &calling_class,
                    1)) {
    ThrowIllegalAccessException(
            StringPrintf("Class %s cannot access %s field %s of class %s",
                calling_class == nullptr ? "null" : calling_class->PrettyClass().c_str(),
                PrettyJavaAccessFlags(field->GetAccessFlags()).c_str(),
                ArtField::PrettyField(field->GetArtField()).c_str(),
                field->GetDeclaringClass() == nullptr ? "null" :
                    field->GetDeclaringClass()->PrettyClass().c_str()).c_str());
    return false;
  }
  return true;
}

template<bool kAllowReferences>
ALWAYS_INLINE inline static bool GetFieldValue(const ScopedFastNativeObjectAccess& soa,
                                               ObjPtr<mirror::Object> o,
                                               ObjPtr<mirror::Field> f,
                                               Primitive::Type field_type,
                                               JValue* value)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  DCHECK_EQ(value->GetJ(), INT64_C(0));
  MemberOffset offset(f->GetOffset());
  const bool is_volatile = f->IsVolatile();
  switch (field_type) {
    case Primitive::kPrimBoolean:
      value->SetZ(is_volatile ? o->GetFieldBooleanVolatile(offset) : o->GetFieldBoolean(offset));
      return true;
    case Primitive::kPrimByte:
      value->SetB(is_volatile ? o->GetFieldByteVolatile(offset) : o->GetFieldByte(offset));
      return true;
    case Primitive::kPrimChar:
      value->SetC(is_volatile ? o->GetFieldCharVolatile(offset) : o->GetFieldChar(offset));
      return true;
    case Primitive::kPrimInt:
    case Primitive::kPrimFloat:
      value->SetI(is_volatile ? o->GetField32Volatile(offset) : o->GetField32(offset));
      return true;
    case Primitive::kPrimLong:
    case Primitive::kPrimDouble:
      value->SetJ(is_volatile ? o->GetField64Volatile(offset) : o->GetField64(offset));
      return true;
    case Primitive::kPrimShort:
      value->SetS(is_volatile ? o->GetFieldShortVolatile(offset) : o->GetFieldShort(offset));
      return true;
    case Primitive::kPrimNot:
      if (kAllowReferences) {
        // We need to ensure that a Reference-type object's referent is fetched
        // via GetReferent and not directly using a read-barrier (See b/174433134)
        const uint32_t class_flags = o->GetClass()->GetClassFlags();
        if (UNLIKELY((class_flags & mirror::kClassFlagReference) != 0 &&
                     mirror::Reference::ReferentOffset() == offset)) {
          // PhantomReference's get() always returns null.
          value->SetL((class_flags & mirror::kClassFlagPhantomReference) != 0
                          ? nullptr
                          : Runtime::Current()->GetHeap()->GetReferenceProcessor()->GetReferent(
                                  soa.Self(), o->AsReference()));
        } else {
          value->SetL(is_volatile ? o->GetFieldObjectVolatile<mirror::Object>(offset) :
                      o->GetFieldObject<mirror::Object>(offset));
        }
        return true;
      }
      // Else break to report an error.
      break;
    case Primitive::kPrimVoid:
      // Never okay.
      break;
  }
  ThrowIllegalArgumentException(
      StringPrintf("Not a primitive field: %s",
                   ArtField::PrettyField(f->GetArtField()).c_str()).c_str());
  return false;
}

ALWAYS_INLINE inline static bool CheckReceiver(const ScopedFastNativeObjectAccess& soa,
                                               jobject j_rcvr,
                                               ObjPtr<mirror::Field>* f,
                                               ObjPtr<mirror::Object>* class_or_rcvr)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  soa.Self()->AssertThreadSuspensionIsAllowable();
  ObjPtr<mirror::Class> declaring_class = (*f)->GetDeclaringClass();
  if ((*f)->IsStatic()) {
    if (UNLIKELY(!declaring_class->IsVisiblyInitialized())) {
      Thread* self = soa.Self();
      StackHandleScope<2> hs(self);
      HandleWrapperObjPtr<mirror::Field> h_f(hs.NewHandleWrapper(f));
      HandleWrapperObjPtr<mirror::Class> h_klass(hs.NewHandleWrapper(&declaring_class));
      if (UNLIKELY(!Runtime::Current()->GetClassLinker()->EnsureInitialized(
                        self, h_klass, /*can_init_fields=*/ true, /*can_init_parents=*/ true))) {
        DCHECK(self->IsExceptionPending());
        return false;
      }
      DCHECK(h_klass->IsInitializing());
    }
    *class_or_rcvr = declaring_class;
    return true;
  }
  *class_or_rcvr = soa.Decode<mirror::Object>(j_rcvr);
  if (!VerifyObjectIsClass(*class_or_rcvr, declaring_class)) {
    DCHECK(soa.Self()->IsExceptionPending());
    return false;
  }
  return true;
}

static jobject Field_get(JNIEnv* env, jobject javaField, jobject javaObj) {
  ScopedFastNativeObjectAccess soa(env);
  ObjPtr<mirror::Field> f = soa.Decode<mirror::Field>(javaField);
  ObjPtr<mirror::Object> o;
  if (!CheckReceiver(soa, javaObj, &f, &o)) {
    DCHECK(soa.Self()->IsExceptionPending());
    return nullptr;
  }
  // If field is not set to be accessible, verify it can be accessed by the caller.
  if (!f->IsAccessible() && !VerifyFieldAccess<false>(soa.Self(), f, o)) {
    DCHECK(soa.Self()->IsExceptionPending());
    return nullptr;
  }
  // We now don't expect suspension unless an exception is thrown.
  // Get the field's value, boxing if necessary.
  Primitive::Type field_type = f->GetTypeAsPrimitiveType();
  JValue value;
  if (!GetFieldValue<true>(soa, o, f, field_type, &value)) {
    DCHECK(soa.Self()->IsExceptionPending());
    return nullptr;
  }
  return soa.AddLocalReference<jobject>(BoxPrimitive(field_type, value));
}

template<Primitive::Type kPrimitiveType>
ALWAYS_INLINE inline static JValue GetPrimitiveField(JNIEnv* env,
                                                     jobject javaField,
                                                     jobject javaObj) {
  ScopedFastNativeObjectAccess soa(env);
  ObjPtr<mirror::Field> f = soa.Decode<mirror::Field>(javaField);
  ObjPtr<mirror::Object> o;
  if (!CheckReceiver(soa, javaObj, &f, &o)) {
    DCHECK(soa.Self()->IsExceptionPending());
    return JValue();
  }

  // If field is not set to be accessible, verify it can be accessed by the caller.
  if (!f->IsAccessible() && !VerifyFieldAccess<false>(soa.Self(), f, o)) {
    DCHECK(soa.Self()->IsExceptionPending());
    return JValue();
  }

  // We now don't expect suspension unless an exception is thrown.
  // Read the value.
  Primitive::Type field_type = f->GetTypeAsPrimitiveType();
  JValue field_value;
  if (field_type == kPrimitiveType) {
    // This if statement should get optimized out since we only pass in valid primitive types.
    if (UNLIKELY(!GetFieldValue<false>(soa, o, f, kPrimitiveType, &field_value))) {
      DCHECK(soa.Self()->IsExceptionPending());
      return JValue();
    }
    return field_value;
  }
  if (!GetFieldValue<false>(soa, o, f, field_type, &field_value)) {
    DCHECK(soa.Self()->IsExceptionPending());
    return JValue();
  }
  // Widen it if necessary (and possible).
  JValue wide_value;
  if (!ConvertPrimitiveValue(false, field_type, kPrimitiveType, field_value,
                             &wide_value)) {
    DCHECK(soa.Self()->IsExceptionPending());
    return JValue();
  }
  return wide_value;
}

static jboolean Field_getBoolean(JNIEnv* env, jobject javaField, jobject javaObj) {
  return GetPrimitiveField<Primitive::kPrimBoolean>(env, javaField, javaObj).GetZ();
}

static jbyte Field_getByte(JNIEnv* env, jobject javaField, jobject javaObj) {
  return GetPrimitiveField<Primitive::kPrimByte>(env, javaField, javaObj).GetB();
}

static jchar Field_getChar(JNIEnv* env, jobject javaField, jobject javaObj) {
  return GetPrimitiveField<Primitive::kPrimChar>(env, javaField, javaObj).GetC();
}

static jdouble Field_getDouble(JNIEnv* env, jobject javaField, jobject javaObj) {
  return GetPrimitiveField<Primitive::kPrimDouble>(env, javaField, javaObj).GetD();
}

static jfloat Field_getFloat(JNIEnv* env, jobject javaField, jobject javaObj) {
  return GetPrimitiveField<Primitive::kPrimFloat>(env, javaField, javaObj).GetF();
}

static jint Field_getInt(JNIEnv* env, jobject javaField, jobject javaObj) {
  return GetPrimitiveField<Primitive::kPrimInt>(env, javaField, javaObj).GetI();
}

static jlong Field_getLong(JNIEnv* env, jobject javaField, jobject javaObj) {
  return GetPrimitiveField<Primitive::kPrimLong>(env, javaField, javaObj).GetJ();
}

static jshort Field_getShort(JNIEnv* env, jobject javaField, jobject javaObj) {
  return GetPrimitiveField<Primitive::kPrimShort>(env, javaField, javaObj).GetS();
}

ALWAYS_INLINE inline static void SetFieldValue(ObjPtr<mirror::Object> o,
                                               ObjPtr<mirror::Field> f,
                                               Primitive::Type field_type,
                                               bool allow_references,
                                               const JValue& new_value)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  DCHECK(f->GetDeclaringClass()->IsInitializing());
  MemberOffset offset(f->GetOffset());
  const bool is_volatile = f->IsVolatile();
  switch (field_type) {
  case Primitive::kPrimBoolean:
    if (is_volatile) {
      o->SetFieldBooleanVolatile<false>(offset, new_value.GetZ());
    } else {
      o->SetFieldBoolean<false>(offset, new_value.GetZ());
    }
    break;
  case Primitive::kPrimByte:
    if (is_volatile) {
      o->SetFieldBooleanVolatile<false>(offset, new_value.GetB());
    } else {
      o->SetFieldBoolean<false>(offset, new_value.GetB());
    }
    break;
  case Primitive::kPrimChar:
    if (is_volatile) {
      o->SetFieldCharVolatile<false>(offset, new_value.GetC());
    } else {
      o->SetFieldChar<false>(offset, new_value.GetC());
    }
    break;
  case Primitive::kPrimInt:
  case Primitive::kPrimFloat:
    if (is_volatile) {
      o->SetField32Volatile<false>(offset, new_value.GetI());
    } else {
      o->SetField32<false>(offset, new_value.GetI());
    }
    break;
  case Primitive::kPrimLong:
  case Primitive::kPrimDouble:
    if (is_volatile) {
      o->SetField64Volatile<false>(offset, new_value.GetJ());
    } else {
      o->SetField64<false>(offset, new_value.GetJ());
    }
    break;
  case Primitive::kPrimShort:
    if (is_volatile) {
      o->SetFieldShortVolatile<false>(offset, new_value.GetS());
    } else {
      o->SetFieldShort<false>(offset, new_value.GetS());
    }
    break;
  case Primitive::kPrimNot:
    if (allow_references) {
      if (is_volatile) {
        o->SetFieldObjectVolatile<false>(offset, new_value.GetL());
      } else {
        o->SetFieldObject<false>(offset, new_value.GetL());
      }
      break;
    }
    // Else fall through to report an error.
    FALLTHROUGH_INTENDED;
  case Primitive::kPrimVoid:
    // Never okay.
    ThrowIllegalArgumentException(
        StringPrintf("Not a primitive field: %s",
                     ArtField::PrettyField(f->GetArtField()).c_str()).c_str());
    return;
  }
}

ALWAYS_INLINE inline static bool ThrowIAEIfRecordFinalField(ObjPtr<mirror::Field> field)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  if (!(field->IsFinal())) {
    return false;
  }
  ObjPtr<mirror::Class> declaring_class = field->GetDeclaringClass();
  DCHECK(declaring_class != nullptr);
  if (!(declaring_class->IsRecordClass())) {
    return false;
  }

  ThrowIllegalAccessException(
          StringPrintf("Cannot set %s field %s of record class %s",
              PrettyJavaAccessFlags(field->GetAccessFlags()).c_str(),
              ArtField::PrettyField(field->GetArtField()).c_str(),
              declaring_class->PrettyClass().c_str()).c_str());

  return true;
}

static void Field_set(JNIEnv* env, jobject javaField, jobject javaObj, jobject javaValue) {
  ScopedFastNativeObjectAccess soa(env);
  ObjPtr<mirror::Field> f = soa.Decode<mirror::Field>(javaField);
  // Check that the receiver is non-null and an instance of the field's declaring class.
  ObjPtr<mirror::Object> o;
  if (!CheckReceiver(soa, javaObj, &f, &o)) {
    DCHECK(soa.Self()->IsExceptionPending());
    return;
  }
  if (ThrowIAEIfRecordFinalField(f)) {
    DCHECK(soa.Self()->IsExceptionPending());
    return;
  }
  ObjPtr<mirror::Class> field_type;
  const char* field_type_descriptor = f->GetArtField()->GetTypeDescriptor();
  Primitive::Type field_prim_type = Primitive::GetType(field_type_descriptor[0]);
  if (field_prim_type == Primitive::kPrimNot) {
    field_type = f->GetType();
  } else {
    field_type =
        Runtime::Current()->GetClassLinker()->LookupPrimitiveClass(field_type_descriptor[0]);
  }
  DCHECK(field_type != nullptr) << field_type_descriptor;
  // We now don't expect suspension unless an exception is thrown.
  // Unbox the value, if necessary.
  ObjPtr<mirror::Object> boxed_value = soa.Decode<mirror::Object>(javaValue);
  JValue unboxed_value;
  if (!UnboxPrimitiveForField(boxed_value,
                              field_type,
                              f->GetArtField(),
                              &unboxed_value)) {
    DCHECK(soa.Self()->IsExceptionPending());
    return;
  }
  // If field is not set to be accessible, verify it can be accessed by the caller.
  if (!f->IsAccessible() && !VerifyFieldAccess<true>(soa.Self(), f, o)) {
    DCHECK(soa.Self()->IsExceptionPending());
    return;
  }
  SetFieldValue(o, f, field_prim_type, true, unboxed_value);
}

template<Primitive::Type kPrimitiveType>
static void SetPrimitiveField(JNIEnv* env,
                              jobject javaField,
                              jobject javaObj,
                              const JValue& new_value) {
  ScopedFastNativeObjectAccess soa(env);
  ObjPtr<mirror::Field> f = soa.Decode<mirror::Field>(javaField);
  ObjPtr<mirror::Object> o;
  if (!CheckReceiver(soa, javaObj, &f, &o)) {
    return;
  }
  if (ThrowIAEIfRecordFinalField(f)) {
    DCHECK(soa.Self()->IsExceptionPending());
    return;
  }
  Primitive::Type field_type = f->GetTypeAsPrimitiveType();
  if (UNLIKELY(field_type == Primitive::kPrimNot)) {
    ThrowIllegalArgumentException(
        StringPrintf("Not a primitive field: %s",
                     ArtField::PrettyField(f->GetArtField()).c_str()).c_str());
    return;
  }

  // Widen the value if necessary (and possible).
  JValue wide_value;
  if (!ConvertPrimitiveValue(false, kPrimitiveType, field_type, new_value, &wide_value)) {
    DCHECK(soa.Self()->IsExceptionPending());
    return;
  }

  // If field is not set to be accessible, verify it can be accessed by the caller.
  if (!f->IsAccessible() && !VerifyFieldAccess<true>(soa.Self(), f, o)) {
    DCHECK(soa.Self()->IsExceptionPending());
    return;
  }

  // Write the value.
  SetFieldValue(o, f, field_type, false, wide_value);
}

static void Field_setBoolean(JNIEnv* env, jobject javaField, jobject javaObj, jboolean z) {
  JValue value;
  value.SetZ(z);
  SetPrimitiveField<Primitive::kPrimBoolean>(env, javaField, javaObj, value);
}

static void Field_setByte(JNIEnv* env, jobject javaField, jobject javaObj, jbyte b) {
  JValue value;
  value.SetB(b);
  SetPrimitiveField<Primitive::kPrimByte>(env, javaField, javaObj, value);
}

static void Field_setChar(JNIEnv* env, jobject javaField, jobject javaObj, jchar c) {
  JValue value;
  value.SetC(c);
  SetPrimitiveField<Primitive::kPrimChar>(env, javaField, javaObj, value);
}

static void Field_setDouble(JNIEnv* env, jobject javaField, jobject javaObj, jdouble d) {
  JValue value;
  value.SetD(d);
  SetPrimitiveField<Primitive::kPrimDouble>(env, javaField, javaObj, value);
}

static void Field_setFloat(JNIEnv* env, jobject javaField, jobject javaObj, jfloat f) {
  JValue value;
  value.SetF(f);
  SetPrimitiveField<Primitive::kPrimFloat>(env, javaField, javaObj, value);
}

static void Field_setInt(JNIEnv* env, jobject javaField, jobject javaObj, jint i) {
  JValue value;
  value.SetI(i);
  SetPrimitiveField<Primitive::kPrimInt>(env, javaField, javaObj, value);
}

static void Field_setLong(JNIEnv* env, jobject javaField, jobject javaObj, jlong j) {
  JValue value;
  value.SetJ(j);
  SetPrimitiveField<Primitive::kPrimLong>(env, javaField, javaObj, value);
}

static void Field_setShort(JNIEnv* env, jobject javaField, jobject javaObj, jshort s) {
  JValue value;
  value.SetS(s);
  SetPrimitiveField<Primitive::kPrimShort>(env, javaField, javaObj, value);
}

static jobject Field_getAnnotationNative(JNIEnv* env, jobject javaField, jclass annotationType) {
  ScopedFastNativeObjectAccess soa(env);
  StackHandleScope<1> hs(soa.Self());
  ArtField* field = soa.Decode<mirror::Field>(javaField)->GetArtField();
  if (field->GetDeclaringClass()->IsProxyClass()) {
    return nullptr;
  }
  Handle<mirror::Class> klass(hs.NewHandle(soa.Decode<mirror::Class>(annotationType)));
  return soa.AddLocalReference<jobject>(annotations::GetAnnotationForField(field, klass));
}

static jlong Field_getArtField(JNIEnv* env, jobject javaField) {
  ScopedFastNativeObjectAccess soa(env);
  ArtField* field = soa.Decode<mirror::Field>(javaField)->GetArtField();
  return reinterpret_cast<jlong>(field);
}

static jstring Field_getNameInternal(JNIEnv* env, jobject javaField) {
  ScopedFastNativeObjectAccess soa(env);
  ArtField* field = soa.Decode<mirror::Field>(javaField)->GetArtField();
  return soa.AddLocalReference<jstring>(field->ResolveNameString());
}

static jobjectArray Field_getDeclaredAnnotations(JNIEnv* env, jobject javaField) {
  ScopedFastNativeObjectAccess soa(env);
  ArtField* field = soa.Decode<mirror::Field>(javaField)->GetArtField();
  if (field->GetDeclaringClass()->IsProxyClass()) {
    // Return an empty array instead of a null pointer.
    ObjPtr<mirror::Class> annotation_array_class =
        WellKnownClasses::ToClass(WellKnownClasses::java_lang_annotation_Annotation__array);
    ObjPtr<mirror::ObjectArray<mirror::Object>> empty_array =
        mirror::ObjectArray<mirror::Object>::Alloc(soa.Self(), annotation_array_class, 0);
    return soa.AddLocalReference<jobjectArray>(empty_array);
  }
  return soa.AddLocalReference<jobjectArray>(annotations::GetAnnotationsForField(field));
}

static jobjectArray Field_getSignatureAnnotation(JNIEnv* env, jobject javaField) {
  ScopedFastNativeObjectAccess soa(env);
  ArtField* field = soa.Decode<mirror::Field>(javaField)->GetArtField();
  if (field->GetDeclaringClass()->IsProxyClass()) {
    return nullptr;
  }
  return soa.AddLocalReference<jobjectArray>(annotations::GetSignatureAnnotationForField(field));
}

static jboolean Field_isAnnotationPresentNative(JNIEnv* env,
                                                jobject javaField,
                                                jclass annotationType) {
  ScopedFastNativeObjectAccess soa(env);
  StackHandleScope<1> hs(soa.Self());
  ArtField* field = soa.Decode<mirror::Field>(javaField)->GetArtField();
  if (field->GetDeclaringClass()->IsProxyClass()) {
    return false;
  }
  Handle<mirror::Class> klass(hs.NewHandle(soa.Decode<mirror::Class>(annotationType)));
  return annotations::IsFieldAnnotationPresent(field, klass);
}

static JNINativeMethod gMethods[] = {
  FAST_NATIVE_METHOD(Field, get,        "(Ljava/lang/Object;)Ljava/lang/Object;"),
  FAST_NATIVE_METHOD(Field, getBoolean, "(Ljava/lang/Object;)Z"),
  FAST_NATIVE_METHOD(Field, getByte,    "(Ljava/lang/Object;)B"),
  FAST_NATIVE_METHOD(Field, getChar,    "(Ljava/lang/Object;)C"),
  FAST_NATIVE_METHOD(Field, getAnnotationNative,
                "(Ljava/lang/Class;)Ljava/lang/annotation/Annotation;"),
  FAST_NATIVE_METHOD(Field, getArtField, "()J"),
  FAST_NATIVE_METHOD(Field, getDeclaredAnnotations, "()[Ljava/lang/annotation/Annotation;"),
  FAST_NATIVE_METHOD(Field, getSignatureAnnotation, "()[Ljava/lang/String;"),
  FAST_NATIVE_METHOD(Field, getDouble,  "(Ljava/lang/Object;)D"),
  FAST_NATIVE_METHOD(Field, getFloat,   "(Ljava/lang/Object;)F"),
  FAST_NATIVE_METHOD(Field, getInt,     "(Ljava/lang/Object;)I"),
  FAST_NATIVE_METHOD(Field, getLong,    "(Ljava/lang/Object;)J"),
  FAST_NATIVE_METHOD(Field, getNameInternal, "()Ljava/lang/String;"),
  FAST_NATIVE_METHOD(Field, getShort,   "(Ljava/lang/Object;)S"),
  FAST_NATIVE_METHOD(Field, isAnnotationPresentNative, "(Ljava/lang/Class;)Z"),
  FAST_NATIVE_METHOD(Field, set,        "(Ljava/lang/Object;Ljava/lang/Object;)V"),
  FAST_NATIVE_METHOD(Field, setBoolean, "(Ljava/lang/Object;Z)V"),
  FAST_NATIVE_METHOD(Field, setByte,    "(Ljava/lang/Object;B)V"),
  FAST_NATIVE_METHOD(Field, setChar,    "(Ljava/lang/Object;C)V"),
  FAST_NATIVE_METHOD(Field, setDouble,  "(Ljava/lang/Object;D)V"),
  FAST_NATIVE_METHOD(Field, setFloat,   "(Ljava/lang/Object;F)V"),
  FAST_NATIVE_METHOD(Field, setInt,     "(Ljava/lang/Object;I)V"),
  FAST_NATIVE_METHOD(Field, setLong,    "(Ljava/lang/Object;J)V"),
  FAST_NATIVE_METHOD(Field, setShort,   "(Ljava/lang/Object;S)V"),
};

void register_java_lang_reflect_Field(JNIEnv* env) {
  REGISTER_NATIVE_METHODS("java/lang/reflect/Field");
}

}  // namespace art
