Add AccessibleObject and Field to mirror
Main motivation is to remove all the functionality / field access on
java side to ArtField. Also comes with some reflection speedups /
slowdowns.
Summary results:
getDeclaredField/getField are slower mostly due to JNI overhead.
However, there is a large speedup in getInt, setInt,
GetInstanceField, and GetStaticField.
Before timings (N5 --compiler-filter=everything):
benchmark ns linear runtime
Class_getDeclaredField 782.86 ===
Class_getField 832.77 ===
Field_getInt 160.17 =
Field_setInt 195.88 =
GetInstanceField 3214.38 ==============
GetStaticField 6809.49 ==============================
After:
Class_getDeclaredField 1068.15 ============
Class_getField 1180.00 ==============
Field_getInt 121.85 =
Field_setInt 139.98 =
GetInstanceField 1986.15 =======================
GetStaticField 2523.63 ==============================
Bug: 19264997
Change-Id: Ic0d0fc1b56b95cd6d60f8e76f19caeaa23045c77
diff --git a/runtime/native/java_lang_Class.cc b/runtime/native/java_lang_Class.cc
index 60d14e9..3cb6b36 100644
--- a/runtime/native/java_lang_Class.cc
+++ b/runtime/native/java_lang_Class.cc
@@ -17,21 +17,28 @@
#include "java_lang_Class.h"
#include "class_linker.h"
+#include "common_throws.h"
#include "dex_file-inl.h"
#include "jni_internal.h"
#include "nth_caller_visitor.h"
+#include "mirror/art_field-inl.h"
#include "mirror/class-inl.h"
#include "mirror/class_loader.h"
+#include "mirror/field.h"
#include "mirror/object-inl.h"
+#include "mirror/object_array-inl.h"
+#include "mirror/string-inl.h"
#include "scoped_thread_state_change.h"
#include "scoped_fast_native_object_access.h"
#include "ScopedLocalRef.h"
#include "ScopedUtfChars.h"
+#include "utf.h"
#include "well_known_classes.h"
namespace art {
-static mirror::Class* DecodeClass(const ScopedFastNativeObjectAccess& soa, jobject java_class)
+ALWAYS_INLINE static inline mirror::Class* DecodeClass(
+ const ScopedFastNativeObjectAccess& soa, jobject java_class)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
mirror::Class* c = soa.Decode<mirror::Class*>(java_class);
DCHECK(c != NULL);
@@ -97,10 +104,170 @@
return soa.AddLocalReference<jobjectArray>(c->GetInterfaces()->Clone(soa.Self()));
}
+static mirror::ObjectArray<mirror::Field>* GetDeclaredFields(
+ Thread* self, mirror::Class* klass, bool public_only, bool force_resolve)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ StackHandleScope<3> hs(self);
+ auto h_ifields = hs.NewHandle(klass->GetIFields());
+ auto h_sfields = hs.NewHandle(klass->GetSFields());
+ const int32_t num_ifields = h_ifields.Get() != nullptr ? h_ifields->GetLength() : 0;
+ const int32_t num_sfields = h_sfields.Get() != nullptr ? h_sfields->GetLength() : 0;
+ int32_t array_size = num_ifields + num_sfields;
+ if (public_only) {
+ // Lets go subtract all the non public fields.
+ for (int32_t i = 0; i < num_ifields; ++i) {
+ if (!h_ifields->GetWithoutChecks(i)->IsPublic()) {
+ --array_size;
+ }
+ }
+ for (int32_t i = 0; i < num_sfields; ++i) {
+ if (!h_sfields->GetWithoutChecks(i)->IsPublic()) {
+ --array_size;
+ }
+ }
+ }
+ int32_t array_idx = 0;
+ auto object_array = hs.NewHandle(mirror::ObjectArray<mirror::Field>::Alloc(
+ self, mirror::Field::ArrayClass(), array_size));
+ if (object_array.Get() == nullptr) {
+ return nullptr;
+ }
+ for (int32_t i = 0; i < num_ifields; ++i) {
+ auto* art_field = h_ifields->GetWithoutChecks(i);
+ if (!public_only || art_field->IsPublic()) {
+ auto* field = mirror::Field::CreateFromArtField(self, art_field, force_resolve);
+ if (field == nullptr) {
+ if (kIsDebugBuild) {
+ self->AssertPendingException();
+ }
+ // Maybe null due to OOME or type resolving exception.
+ return nullptr;
+ }
+ object_array->SetWithoutChecks<false>(array_idx++, field);
+ }
+ }
+ for (int32_t i = 0; i < num_sfields; ++i) {
+ auto* art_field = h_sfields->GetWithoutChecks(i);
+ if (!public_only || art_field->IsPublic()) {
+ auto* field = mirror::Field::CreateFromArtField(self, art_field, force_resolve);
+ if (field == nullptr) {
+ if (kIsDebugBuild) {
+ self->AssertPendingException();
+ }
+ return nullptr;
+ }
+ object_array->SetWithoutChecks<false>(array_idx++, field);
+ }
+ }
+ CHECK_EQ(array_idx, array_size);
+ return object_array.Get();
+}
+
+static jobjectArray Class_getDeclaredFieldsUnchecked(JNIEnv* env, jobject javaThis,
+ jboolean publicOnly) {
+ ScopedFastNativeObjectAccess soa(env);
+ return soa.AddLocalReference<jobjectArray>(
+ GetDeclaredFields(soa.Self(), DecodeClass(soa, javaThis), publicOnly != JNI_FALSE, false));
+}
+
+static jobjectArray Class_getDeclaredFields(JNIEnv* env, jobject javaThis) {
+ ScopedFastNativeObjectAccess soa(env);
+ return soa.AddLocalReference<jobjectArray>(
+ GetDeclaredFields(soa.Self(), DecodeClass(soa, javaThis), false, true));
+}
+
+static jobjectArray Class_getPublicDeclaredFields(JNIEnv* env, jobject javaThis) {
+ ScopedFastNativeObjectAccess soa(env);
+ return soa.AddLocalReference<jobjectArray>(
+ GetDeclaredFields(soa.Self(), DecodeClass(soa, javaThis), true, true));
+}
+
+// Performs a binary search through an array of fields, TODO: Is this fast enough if we don't use
+// the dex cache for lookups? I think CompareModifiedUtf8ToUtf16AsCodePointValues should be fairly
+// fast.
+ALWAYS_INLINE static inline mirror::ArtField* FindFieldByName(
+ Thread* self ATTRIBUTE_UNUSED, mirror::String* name,
+ mirror::ObjectArray<mirror::ArtField>* fields)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ uint32_t low = 0;
+ uint32_t high = fields->GetLength();
+ const uint16_t* const data = name->GetCharArray()->GetData() + name->GetOffset();
+ const size_t length = name->GetLength();
+ while (low < high) {
+ auto mid = (low + high) / 2;
+ mirror::ArtField* const field = fields->GetWithoutChecks(mid);
+ int result = CompareModifiedUtf8ToUtf16AsCodePointValues(field->GetName(), data, length);
+ // Alternate approach, only a few % faster at the cost of more allocations.
+ // int result = field->GetStringName(self, true)->CompareTo(name);
+ if (result < 0) {
+ low = mid + 1;
+ } else if (result > 0) {
+ high = mid;
+ } else {
+ return field;
+ }
+ }
+ if (kIsDebugBuild) {
+ for (int32_t i = 0; i < fields->GetLength(); ++i) {
+ CHECK_NE(fields->GetWithoutChecks(i)->GetName(), name->ToModifiedUtf8());
+ }
+ }
+ return nullptr;
+}
+
+ALWAYS_INLINE static inline mirror::Field* GetDeclaredField(
+ Thread* self, mirror::Class* c, mirror::String* name)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ auto* instance_fields = c->GetIFields();
+ if (instance_fields != nullptr) {
+ auto* art_field = FindFieldByName(self, name, instance_fields);
+ if (art_field != nullptr) {
+ return mirror::Field::CreateFromArtField(self, art_field, true);
+ }
+ }
+ auto* static_fields = c->GetSFields();
+ if (static_fields != nullptr) {
+ auto* art_field = FindFieldByName(self, name, static_fields);
+ if (art_field != nullptr) {
+ return mirror::Field::CreateFromArtField(self, art_field, true);
+ }
+ }
+ return nullptr;
+}
+
+static jobject Class_getDeclaredFieldInternal(JNIEnv* env, jobject javaThis, jstring name) {
+ ScopedFastNativeObjectAccess soa(env);
+ auto* name_string = soa.Decode<mirror::String*>(name);
+ return soa.AddLocalReference<jobject>(
+ GetDeclaredField(soa.Self(), DecodeClass(soa, javaThis), name_string));
+}
+
+static jobject Class_getDeclaredField(JNIEnv* env, jobject javaThis, jstring name) {
+ ScopedFastNativeObjectAccess soa(env);
+ auto* name_string = soa.Decode<mirror::String*>(name);
+ if (name == nullptr) {
+ ThrowNullPointerException("name == null");
+ return nullptr;
+ }
+ auto* klass = DecodeClass(soa, javaThis);
+ mirror::Field* result = GetDeclaredField(soa.Self(), klass, name_string);
+ if (result == nullptr) {
+ std::string name_str = name_string->ToModifiedUtf8();
+ soa.Self()->ThrowNewException("Ljava/lang/NoSuchFieldException;", name_str.c_str());
+ return nullptr;
+ }
+ return soa.AddLocalReference<jobject>(result);
+}
+
static JNINativeMethod gMethods[] = {
NATIVE_METHOD(Class, classForName, "!(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;"),
NATIVE_METHOD(Class, getNameNative, "!()Ljava/lang/String;"),
NATIVE_METHOD(Class, getProxyInterfaces, "!()[Ljava/lang/Class;"),
+ NATIVE_METHOD(Class, getDeclaredFields, "!()[Ljava/lang/reflect/Field;"),
+ NATIVE_METHOD(Class, getPublicDeclaredFields, "!()[Ljava/lang/reflect/Field;"),
+ NATIVE_METHOD(Class, getDeclaredFieldsUnchecked, "!(Z)[Ljava/lang/reflect/Field;"),
+ NATIVE_METHOD(Class, getDeclaredFieldInternal, "!(Ljava/lang/String;)Ljava/lang/reflect/Field;"),
+ NATIVE_METHOD(Class, getDeclaredField, "!(Ljava/lang/String;)Ljava/lang/reflect/Field;"),
};
void register_java_lang_Class(JNIEnv* env) {
diff --git a/runtime/native/java_lang_reflect_Field.cc b/runtime/native/java_lang_reflect_Field.cc
index 9c5bde9..0fe78b3 100644
--- a/runtime/native/java_lang_reflect_Field.cc
+++ b/runtime/native/java_lang_reflect_Field.cc
@@ -21,23 +21,23 @@
#include "common_throws.h"
#include "dex_file-inl.h"
#include "jni_internal.h"
-#include "mirror/art_field-inl.h"
#include "mirror/art_method-inl.h"
#include "mirror/class-inl.h"
+#include "mirror/field.h"
#include "reflection-inl.h"
#include "scoped_fast_native_object_access.h"
namespace art {
template<bool kIsSet>
-ALWAYS_INLINE inline static bool VerifyFieldAccess(Thread* self, mirror::ArtField* field,
+ALWAYS_INLINE inline static bool VerifyFieldAccess(Thread* self, mirror::Field* field,
mirror::Object* obj)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
if (kIsSet && field->IsFinal()) {
ThrowIllegalAccessException(
StringPrintf("Cannot set %s field %s of class %s",
PrettyJavaAccessFlags(field->GetAccessFlags()).c_str(),
- PrettyField(field).c_str(),
+ PrettyField(field->GetArtField()).c_str(),
field->GetDeclaringClass() == nullptr ? "null" :
PrettyClass(field->GetDeclaringClass()).c_str()).c_str());
return false;
@@ -49,7 +49,7 @@
StringPrintf("Class %s cannot access %s field %s of class %s",
calling_class == nullptr ? "null" : PrettyClass(calling_class).c_str(),
PrettyJavaAccessFlags(field->GetAccessFlags()).c_str(),
- PrettyField(field).c_str(),
+ PrettyField(field->GetArtField()).c_str(),
field->GetDeclaringClass() == nullptr ? "null" :
PrettyClass(field->GetDeclaringClass()).c_str()).c_str());
return false;
@@ -58,38 +58,37 @@
}
template<bool kAllowReferences>
-ALWAYS_INLINE inline static bool GetFieldValue(mirror::Object* o, mirror::ArtField* f,
+ALWAYS_INLINE inline static bool GetFieldValue(mirror::Object* o, mirror::Field* f,
Primitive::Type field_type, JValue* value)
SHARED_LOCKS_REQUIRED(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(f->GetBoolean(o));
+ value->SetZ(is_volatile ? o->GetFieldBooleanVolatile(offset) : o->GetFieldBoolean(offset));
return true;
case Primitive::kPrimByte:
- value->SetB(f->GetByte(o));
+ value->SetB(is_volatile ? o->GetFieldByteVolatile(offset) : o->GetFieldByte(offset));
return true;
case Primitive::kPrimChar:
- value->SetC(f->GetChar(o));
- return true;
- case Primitive::kPrimDouble:
- value->SetD(f->GetDouble(o));
- return true;
- case Primitive::kPrimFloat:
- value->SetF(f->GetFloat(o));
+ value->SetC(is_volatile ? o->GetFieldCharVolatile(offset) : o->GetFieldChar(offset));
return true;
case Primitive::kPrimInt:
- value->SetI(f->GetInt(o));
+ case Primitive::kPrimFloat:
+ value->SetI(is_volatile ? o->GetField32Volatile(offset) : o->GetField32(offset));
return true;
case Primitive::kPrimLong:
- value->SetJ(f->GetLong(o));
+ case Primitive::kPrimDouble:
+ value->SetJ(is_volatile ? o->GetField64Volatile(offset) : o->GetField64(offset));
return true;
case Primitive::kPrimShort:
- value->SetS(f->GetShort(o));
+ value->SetS(is_volatile ? o->GetFieldShortVolatile(offset) : o->GetFieldShort(offset));
return true;
case Primitive::kPrimNot:
if (kAllowReferences) {
- value->SetL(f->GetObject(o));
+ value->SetL(is_volatile ? o->GetFieldObjectVolatile<mirror::Object>(offset) :
+ o->GetFieldObject<mirror::Object>(offset));
return true;
}
// Else break to report an error.
@@ -98,23 +97,23 @@
// Never okay.
break;
}
- ThrowIllegalArgumentException(StringPrintf("Not a primitive field: %s",
- PrettyField(f).c_str()).c_str());
+ ThrowIllegalArgumentException(
+ StringPrintf("Not a primitive field: %s", PrettyField(f->GetArtField()).c_str()).c_str());
return false;
}
ALWAYS_INLINE inline static bool CheckReceiver(const ScopedFastNativeObjectAccess& soa,
- jobject j_rcvr, mirror::ArtField** f,
+ jobject j_rcvr, mirror::Field** f,
mirror::Object** class_or_rcvr)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
soa.Self()->AssertThreadSuspensionIsAllowable();
mirror::Class* declaringClass = (*f)->GetDeclaringClass();
if ((*f)->IsStatic()) {
if (UNLIKELY(!declaringClass->IsInitialized())) {
- ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
StackHandleScope<2> hs(soa.Self());
- HandleWrapper<mirror::ArtField> h_f(hs.NewHandleWrapper(f));
+ HandleWrapper<mirror::Field> h_f(hs.NewHandleWrapper(f));
HandleWrapper<mirror::Class> h_klass(hs.NewHandleWrapper(&declaringClass));
+ ClassLinker* const class_linker = Runtime::Current()->GetClassLinker();
if (UNLIKELY(!class_linker->EnsureInitialized(soa.Self(), h_klass, true, true))) {
DCHECK(soa.Self()->IsExceptionPending());
return false;
@@ -131,16 +130,16 @@
return true;
}
-static jobject Field_get(JNIEnv* env, jobject javaField, jobject javaObj, jboolean accessible) {
+static jobject Field_get(JNIEnv* env, jobject javaField, jobject javaObj) {
ScopedFastNativeObjectAccess soa(env);
- mirror::ArtField* f = mirror::ArtField::FromReflectedField(soa, javaField);
+ mirror::Field* f = soa.Decode<mirror::Field*>(javaField);
mirror::Object* o = nullptr;
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 ((accessible == JNI_FALSE) && !VerifyFieldAccess<false>(soa.Self(), f, o)) {
+ if (!f->IsAccessible() && !VerifyFieldAccess<false>(soa.Self(), f, o)) {
DCHECK(soa.Self()->IsExceptionPending());
return nullptr;
}
@@ -157,9 +156,9 @@
template<Primitive::Type kPrimitiveType>
ALWAYS_INLINE inline static JValue GetPrimitiveField(JNIEnv* env, jobject javaField,
- jobject javaObj, jboolean accessible) {
+ jobject javaObj) {
ScopedFastNativeObjectAccess soa(env);
- mirror::ArtField* f = mirror::ArtField::FromReflectedField(soa, javaField);
+ mirror::Field* f = soa.Decode<mirror::Field*>(javaField);
mirror::Object* o = nullptr;
if (!CheckReceiver(soa, javaObj, &f, &o)) {
DCHECK(soa.Self()->IsExceptionPending());
@@ -167,7 +166,7 @@
}
// If field is not set to be accessible, verify it can be accessed by the caller.
- if (accessible == JNI_FALSE && !VerifyFieldAccess<false>(soa.Self(), f, o)) {
+ if (!f->IsAccessible() && !VerifyFieldAccess<false>(soa.Self(), f, o)) {
DCHECK(soa.Self()->IsExceptionPending());
return JValue();
}
@@ -198,72 +197,97 @@
return wide_value;
}
-static jboolean Field_getBoolean(JNIEnv* env, jobject javaField, jobject javaObj,
- jboolean accessible) {
- return GetPrimitiveField<Primitive::kPrimBoolean>(env, javaField, javaObj, accessible).GetZ();
+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, jboolean accessible) {
- return GetPrimitiveField<Primitive::kPrimByte>(env, javaField, javaObj, accessible).GetB();
+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, jboolean accessible) {
- return GetPrimitiveField<Primitive::kPrimChar>(env, javaField, javaObj, accessible).GetC();
+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,
- jboolean accessible) {
- return GetPrimitiveField<Primitive::kPrimDouble>(env, javaField, javaObj, accessible).GetD();
+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, jboolean accessible) {
- return GetPrimitiveField<Primitive::kPrimFloat>(env, javaField, javaObj, accessible).GetF();
+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, jboolean accessible) {
- return GetPrimitiveField<Primitive::kPrimInt>(env, javaField, javaObj, accessible).GetI();
+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, jboolean accessible) {
- return GetPrimitiveField<Primitive::kPrimLong>(env, javaField, javaObj, accessible).GetJ();
+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, jboolean accessible) {
- return GetPrimitiveField<Primitive::kPrimShort>(env, javaField, javaObj, accessible).GetS();
+static jshort Field_getShort(JNIEnv* env, jobject javaField, jobject javaObj) {
+ return GetPrimitiveField<Primitive::kPrimShort>(env, javaField, javaObj).GetS();
}
-static void SetFieldValue(mirror::Object* o, mirror::ArtField* f, Primitive::Type field_type,
- bool allow_references, const JValue& new_value)
+ALWAYS_INLINE inline static void SetFieldValue(mirror::Object* o, mirror::Field* f,
+ Primitive::Type field_type, bool allow_references,
+ const JValue& new_value)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
DCHECK(f->GetDeclaringClass()->IsInitialized());
+ MemberOffset offset(f->GetOffset());
+ const bool is_volatile = f->IsVolatile();
switch (field_type) {
case Primitive::kPrimBoolean:
- f->SetBoolean<false>(o, new_value.GetZ());
+ if (is_volatile) {
+ o->SetFieldBooleanVolatile<false>(offset, new_value.GetZ());
+ } else {
+ o->SetFieldBoolean<false>(offset, new_value.GetZ());
+ }
break;
case Primitive::kPrimByte:
- f->SetByte<false>(o, new_value.GetB());
+ if (is_volatile) {
+ o->SetFieldBooleanVolatile<false>(offset, new_value.GetB());
+ } else {
+ o->SetFieldBoolean<false>(offset, new_value.GetB());
+ }
break;
case Primitive::kPrimChar:
- f->SetChar<false>(o, new_value.GetC());
- break;
- case Primitive::kPrimDouble:
- f->SetDouble<false>(o, new_value.GetD());
- break;
- case Primitive::kPrimFloat:
- f->SetFloat<false>(o, new_value.GetF());
+ if (is_volatile) {
+ o->SetFieldBooleanVolatile<false>(offset, new_value.GetC());
+ } else {
+ o->SetFieldBoolean<false>(offset, new_value.GetC());
+ }
break;
case Primitive::kPrimInt:
- f->SetInt<false>(o, new_value.GetI());
+ 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:
- f->SetLong<false>(o, new_value.GetJ());
+ 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:
- f->SetShort<false>(o, new_value.GetS());
+ if (is_volatile) {
+ o->SetFieldShortVolatile<false>(offset, new_value.GetZ());
+ } else {
+ o->SetFieldShort<false>(offset, new_value.GetZ());
+ }
break;
case Primitive::kPrimNot:
if (allow_references) {
- f->SetObject<false>(o, new_value.GetL());
+ 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.
@@ -271,15 +295,14 @@
case Primitive::kPrimVoid:
// Never okay.
ThrowIllegalArgumentException(StringPrintf("Not a primitive field: %s",
- PrettyField(f).c_str()).c_str());
+ PrettyField(f->GetArtField()).c_str()).c_str());
return;
}
}
-static void Field_set(JNIEnv* env, jobject javaField, jobject javaObj, jobject javaValue,
- jboolean accessible) {
+static void Field_set(JNIEnv* env, jobject javaField, jobject javaObj, jobject javaValue) {
ScopedFastNativeObjectAccess soa(env);
- mirror::ArtField* f = mirror::ArtField::FromReflectedField(soa, javaField);
+ mirror::Field* f = soa.Decode<mirror::Field*>(javaField);
// Check that the receiver is non-null and an instance of the field's declaring class.
mirror::Object* o = nullptr;
if (!CheckReceiver(soa, javaObj, &f, &o)) {
@@ -287,18 +310,11 @@
return;
}
mirror::Class* field_type;
- const char* field_type_desciptor = f->GetTypeDescriptor();
+ const char* field_type_desciptor = f->GetArtField()->GetTypeDescriptor();
Primitive::Type field_prim_type = Primitive::GetType(field_type_desciptor[0]);
if (field_prim_type == Primitive::kPrimNot) {
- StackHandleScope<2> hs(soa.Self());
- HandleWrapper<mirror::Object> h_o(hs.NewHandleWrapper(&o));
- HandleWrapper<mirror::ArtField> h_f(hs.NewHandleWrapper(&f));
- // May cause resolution.
- field_type = h_f->GetType(true);
- if (field_type == nullptr) {
- DCHECK(soa.Self()->IsExceptionPending());
- return;
- }
+ field_type = f->GetType();
+ DCHECK(field_type != nullptr);
} else {
field_type = Runtime::Current()->GetClassLinker()->FindPrimitiveClass(field_type_desciptor[0]);
}
@@ -306,12 +322,12 @@
// Unbox the value, if necessary.
mirror::Object* boxed_value = soa.Decode<mirror::Object*>(javaValue);
JValue unboxed_value;
- if (!UnboxPrimitiveForField(boxed_value, field_type, f, &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 ((accessible == JNI_FALSE) && !VerifyFieldAccess<true>(soa.Self(), f, o)) {
+ if (!f->IsAccessible() && !VerifyFieldAccess<true>(soa.Self(), f, o)) {
DCHECK(soa.Self()->IsExceptionPending());
return;
}
@@ -320,9 +336,9 @@
template<Primitive::Type kPrimitiveType>
static void SetPrimitiveField(JNIEnv* env, jobject javaField, jobject javaObj,
- const JValue& new_value, jboolean accessible) {
+ const JValue& new_value) {
ScopedFastNativeObjectAccess soa(env);
- mirror::ArtField* f = mirror::ArtField::FromReflectedField(soa, javaField);
+ mirror::Field* f = soa.Decode<mirror::Field*>(javaField);
mirror::Object* o = nullptr;
if (!CheckReceiver(soa, javaObj, &f, &o)) {
return;
@@ -330,7 +346,7 @@
Primitive::Type field_type = f->GetTypeAsPrimitiveType();
if (UNLIKELY(field_type == Primitive::kPrimNot)) {
ThrowIllegalArgumentException(StringPrintf("Not a primitive field: %s",
- PrettyField(f).c_str()).c_str());
+ PrettyField(f->GetArtField()).c_str()).c_str());
return;
}
@@ -342,7 +358,7 @@
}
// If field is not set to be accessible, verify it can be accessed by the caller.
- if ((accessible == JNI_FALSE) && !VerifyFieldAccess<true>(soa.Self(), f, o)) {
+ if (!f->IsAccessible() && !VerifyFieldAccess<true>(soa.Self(), f, o)) {
DCHECK(soa.Self()->IsExceptionPending());
return;
}
@@ -351,81 +367,73 @@
SetFieldValue(o, f, field_type, false, wide_value);
}
-static void Field_setBoolean(JNIEnv* env, jobject javaField, jobject javaObj, jboolean z,
- jboolean accessible) {
+static void Field_setBoolean(JNIEnv* env, jobject javaField, jobject javaObj, jboolean z) {
JValue value;
value.SetZ(z);
- SetPrimitiveField<Primitive::kPrimBoolean>(env, javaField, javaObj, value, accessible);
+ SetPrimitiveField<Primitive::kPrimBoolean>(env, javaField, javaObj, value);
}
-static void Field_setByte(JNIEnv* env, jobject javaField, jobject javaObj, jbyte b,
- jboolean accessible) {
+static void Field_setByte(JNIEnv* env, jobject javaField, jobject javaObj, jbyte b) {
JValue value;
value.SetB(b);
- SetPrimitiveField<Primitive::kPrimByte>(env, javaField, javaObj, value, accessible);
+ SetPrimitiveField<Primitive::kPrimByte>(env, javaField, javaObj, value);
}
-static void Field_setChar(JNIEnv* env, jobject javaField, jobject javaObj, jchar c,
- jboolean accessible) {
+static void Field_setChar(JNIEnv* env, jobject javaField, jobject javaObj, jchar c) {
JValue value;
value.SetC(c);
- SetPrimitiveField<Primitive::kPrimChar>(env, javaField, javaObj, value, accessible);
+ SetPrimitiveField<Primitive::kPrimChar>(env, javaField, javaObj, value);
}
-static void Field_setDouble(JNIEnv* env, jobject javaField, jobject javaObj, jdouble d,
- jboolean accessible) {
+static void Field_setDouble(JNIEnv* env, jobject javaField, jobject javaObj, jdouble d) {
JValue value;
value.SetD(d);
- SetPrimitiveField<Primitive::kPrimDouble>(env, javaField, javaObj, value, accessible);
+ SetPrimitiveField<Primitive::kPrimDouble>(env, javaField, javaObj, value);
}
-static void Field_setFloat(JNIEnv* env, jobject javaField, jobject javaObj, jfloat f,
- jboolean accessible) {
+static void Field_setFloat(JNIEnv* env, jobject javaField, jobject javaObj, jfloat f) {
JValue value;
value.SetF(f);
- SetPrimitiveField<Primitive::kPrimFloat>(env, javaField, javaObj, value, accessible);
+ SetPrimitiveField<Primitive::kPrimFloat>(env, javaField, javaObj, value);
}
-static void Field_setInt(JNIEnv* env, jobject javaField, jobject javaObj, jint i,
- jboolean accessible) {
+static void Field_setInt(JNIEnv* env, jobject javaField, jobject javaObj, jint i) {
JValue value;
value.SetI(i);
- SetPrimitiveField<Primitive::kPrimInt>(env, javaField, javaObj, value, accessible);
+ SetPrimitiveField<Primitive::kPrimInt>(env, javaField, javaObj, value);
}
-static void Field_setLong(JNIEnv* env, jobject javaField, jobject javaObj, jlong j,
- jboolean accessible) {
+static void Field_setLong(JNIEnv* env, jobject javaField, jobject javaObj, jlong j) {
JValue value;
value.SetJ(j);
- SetPrimitiveField<Primitive::kPrimLong>(env, javaField, javaObj, value, accessible);
+ SetPrimitiveField<Primitive::kPrimLong>(env, javaField, javaObj, value);
}
-static void Field_setShort(JNIEnv* env, jobject javaField, jobject javaObj, jshort s,
- jboolean accessible) {
+static void Field_setShort(JNIEnv* env, jobject javaField, jobject javaObj, jshort s) {
JValue value;
value.SetS(s);
- SetPrimitiveField<Primitive::kPrimShort>(env, javaField, javaObj, value, accessible);
+ SetPrimitiveField<Primitive::kPrimShort>(env, javaField, javaObj, value);
}
static JNINativeMethod gMethods[] = {
- NATIVE_METHOD(Field, get, "!(Ljava/lang/Object;Z)Ljava/lang/Object;"),
- NATIVE_METHOD(Field, getBoolean, "!(Ljava/lang/Object;Z)Z"),
- NATIVE_METHOD(Field, getByte, "!(Ljava/lang/Object;Z)B"),
- NATIVE_METHOD(Field, getChar, "!(Ljava/lang/Object;Z)C"),
- NATIVE_METHOD(Field, getDouble, "!(Ljava/lang/Object;Z)D"),
- NATIVE_METHOD(Field, getFloat, "!(Ljava/lang/Object;Z)F"),
- NATIVE_METHOD(Field, getInt, "!(Ljava/lang/Object;Z)I"),
- NATIVE_METHOD(Field, getLong, "!(Ljava/lang/Object;Z)J"),
- NATIVE_METHOD(Field, getShort, "!(Ljava/lang/Object;Z)S"),
- NATIVE_METHOD(Field, set, "!(Ljava/lang/Object;Ljava/lang/Object;Z)V"),
- NATIVE_METHOD(Field, setBoolean, "!(Ljava/lang/Object;ZZ)V"),
- NATIVE_METHOD(Field, setByte, "!(Ljava/lang/Object;BZ)V"),
- NATIVE_METHOD(Field, setChar, "!(Ljava/lang/Object;CZ)V"),
- NATIVE_METHOD(Field, setDouble, "!(Ljava/lang/Object;DZ)V"),
- NATIVE_METHOD(Field, setFloat, "!(Ljava/lang/Object;FZ)V"),
- NATIVE_METHOD(Field, setInt, "!(Ljava/lang/Object;IZ)V"),
- NATIVE_METHOD(Field, setLong, "!(Ljava/lang/Object;JZ)V"),
- NATIVE_METHOD(Field, setShort, "!(Ljava/lang/Object;SZ)V"),
+ NATIVE_METHOD(Field, get, "!(Ljava/lang/Object;)Ljava/lang/Object;"),
+ NATIVE_METHOD(Field, getBoolean, "!(Ljava/lang/Object;)Z"),
+ NATIVE_METHOD(Field, getByte, "!(Ljava/lang/Object;)B"),
+ NATIVE_METHOD(Field, getChar, "!(Ljava/lang/Object;)C"),
+ NATIVE_METHOD(Field, getDouble, "!(Ljava/lang/Object;)D"),
+ NATIVE_METHOD(Field, getFloat, "!(Ljava/lang/Object;)F"),
+ NATIVE_METHOD(Field, getInt, "!(Ljava/lang/Object;)I"),
+ NATIVE_METHOD(Field, getLong, "!(Ljava/lang/Object;)J"),
+ NATIVE_METHOD(Field, getShort, "!(Ljava/lang/Object;)S"),
+ NATIVE_METHOD(Field, set, "!(Ljava/lang/Object;Ljava/lang/Object;)V"),
+ NATIVE_METHOD(Field, setBoolean, "!(Ljava/lang/Object;Z)V"),
+ NATIVE_METHOD(Field, setByte, "!(Ljava/lang/Object;B)V"),
+ NATIVE_METHOD(Field, setChar, "!(Ljava/lang/Object;C)V"),
+ NATIVE_METHOD(Field, setDouble, "!(Ljava/lang/Object;D)V"),
+ NATIVE_METHOD(Field, setFloat, "!(Ljava/lang/Object;F)V"),
+ NATIVE_METHOD(Field, setInt, "!(Ljava/lang/Object;I)V"),
+ NATIVE_METHOD(Field, setLong, "!(Ljava/lang/Object;J)V"),
+ NATIVE_METHOD(Field, setShort, "!(Ljava/lang/Object;S)V"),
};
void register_java_lang_reflect_Field(JNIEnv* env) {