diff options
-rw-r--r-- | runtime/mirror/art_field-inl.h | 10 | ||||
-rw-r--r-- | runtime/mirror/art_field.cc | 8 | ||||
-rw-r--r-- | runtime/mirror/art_field.h | 4 | ||||
-rw-r--r-- | runtime/native/java_lang_reflect_Field.cc | 114 | ||||
-rw-r--r-- | runtime/reflection-inl.h | 106 | ||||
-rw-r--r-- | runtime/reflection.cc | 99 | ||||
-rw-r--r-- | runtime/reflection.h | 9 | ||||
-rw-r--r-- | runtime/utils.cc | 4 | ||||
-rw-r--r-- | runtime/utils.h | 4 | ||||
-rw-r--r-- | runtime/utils_test.cc | 12 |
10 files changed, 215 insertions, 155 deletions
diff --git a/runtime/mirror/art_field-inl.h b/runtime/mirror/art_field-inl.h index 00bed92cb3..336d9ee176 100644 --- a/runtime/mirror/art_field-inl.h +++ b/runtime/mirror/art_field-inl.h @@ -25,6 +25,8 @@ #include "jvalue.h" #include "object-inl.h" #include "primitive.h" +#include "scoped_thread_state_change.h" +#include "well_known_classes.h" namespace art { namespace mirror { @@ -284,6 +286,14 @@ inline const DexFile* ArtField::GetDexFile() SHARED_LOCKS_REQUIRED(Locks::mutato return GetDexCache()->GetDexFile(); } +inline ArtField* ArtField::FromReflectedField(const ScopedObjectAccessAlreadyRunnable& soa, + jobject jlr_field) { + mirror::ArtField* f = soa.DecodeField(WellKnownClasses::java_lang_reflect_Field_artField); + mirror::ArtField* field = f->GetObject(soa.Decode<mirror::Object*>(jlr_field))->AsArtField(); + DCHECK(field != nullptr); + return field; +} + } // namespace mirror } // namespace art diff --git a/runtime/mirror/art_field.cc b/runtime/mirror/art_field.cc index 3c7c6ce39a..7e20076112 100644 --- a/runtime/mirror/art_field.cc +++ b/runtime/mirror/art_field.cc @@ -31,14 +31,6 @@ namespace mirror { // TODO: Get global references for these GcRoot<Class> ArtField::java_lang_reflect_ArtField_; -ArtField* ArtField::FromReflectedField(const ScopedObjectAccessAlreadyRunnable& soa, - jobject jlr_field) { - mirror::ArtField* f = soa.DecodeField(WellKnownClasses::java_lang_reflect_Field_artField); - mirror::ArtField* field = f->GetObject(soa.Decode<mirror::Object*>(jlr_field))->AsArtField(); - DCHECK(field != nullptr); - return field; -} - void ArtField::SetClass(Class* java_lang_reflect_ArtField) { CHECK(java_lang_reflect_ArtField_.IsNull()); CHECK(java_lang_reflect_ArtField != NULL); diff --git a/runtime/mirror/art_field.h b/runtime/mirror/art_field.h index f3dfa15004..82d0a6415e 100644 --- a/runtime/mirror/art_field.h +++ b/runtime/mirror/art_field.h @@ -47,8 +47,8 @@ class MANAGED ArtField FINAL : public Object { return sizeof(ArtField); } - static ArtField* FromReflectedField(const ScopedObjectAccessAlreadyRunnable& soa, - jobject jlr_field) + ALWAYS_INLINE static ArtField* FromReflectedField(const ScopedObjectAccessAlreadyRunnable& soa, + jobject jlr_field) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); Class* GetDeclaringClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); diff --git a/runtime/native/java_lang_reflect_Field.cc b/runtime/native/java_lang_reflect_Field.cc index 3903ffcd6a..8850df2eab 100644 --- a/runtime/native/java_lang_reflect_Field.cc +++ b/runtime/native/java_lang_reflect_Field.cc @@ -23,19 +23,21 @@ #include "mirror/art_field-inl.h" #include "mirror/art_method-inl.h" #include "mirror/class-inl.h" -#include "reflection.h" +#include "reflection-inl.h" #include "scoped_fast_native_object_access.h" namespace art { -static bool VerifyFieldAccess(mirror::ArtField* field, mirror::Object* obj, bool is_set) +template<bool kIsSet> +ALWAYS_INLINE inline static bool VerifyFieldAccess(Thread* self, mirror::ArtField* field, + mirror::Object* obj) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - if (field->IsFinal() && is_set) { + if (kIsSet && field->IsFinal()) { ThrowIllegalAccessException(nullptr, StringPrintf("Cannot set final field: %s", PrettyField(field).c_str()).c_str()); return false; } - if (!VerifyAccess(obj, field->GetDeclaringClass(), field->GetAccessFlags())) { + if (!VerifyAccess(self, obj, field->GetDeclaringClass(), field->GetAccessFlags())) { ThrowIllegalAccessException(nullptr, StringPrintf("Cannot access field: %s", PrettyField(field).c_str()).c_str()); return false; @@ -43,9 +45,10 @@ static bool VerifyFieldAccess(mirror::ArtField* field, mirror::Object* obj, bool return true; } -static bool GetFieldValue(const ScopedFastNativeObjectAccess& soa, mirror::Object* o, - mirror::ArtField* f, Primitive::Type field_type, bool allow_references, - JValue* value) +template<bool kAllowReferences> +ALWAYS_INLINE inline static bool GetFieldValue( + const ScopedFastNativeObjectAccess& soa, mirror::Object* o, mirror::ArtField* f, + Primitive::Type field_type, JValue* value) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { DCHECK_EQ(value->GetJ(), INT64_C(0)); switch (field_type) { @@ -74,7 +77,7 @@ static bool GetFieldValue(const ScopedFastNativeObjectAccess& soa, mirror::Objec value->SetS(f->GetShort(o)); return true; case Primitive::kPrimNot: - if (allow_references) { + if (kAllowReferences) { value->SetL(f->GetObject(o)); return true; } @@ -89,28 +92,29 @@ static bool GetFieldValue(const ScopedFastNativeObjectAccess& soa, mirror::Objec return false; } -static bool CheckReceiver(const ScopedFastNativeObjectAccess& soa, jobject j_rcvr, - mirror::ArtField** f, mirror::Object** class_or_rcvr) +ALWAYS_INLINE inline static bool CheckReceiver(const ScopedFastNativeObjectAccess& soa, + jobject j_rcvr, mirror::ArtField** f, + mirror::Object** class_or_rcvr) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { soa.Self()->AssertThreadSuspensionIsAllowable(); + mirror::Class* declaringClass = (*f)->GetDeclaringClass(); if ((*f)->IsStatic()) { - StackHandleScope<2> hs(soa.Self()); - HandleWrapper<mirror::ArtField> h_f(hs.NewHandleWrapper(f)); - Handle<mirror::Class> h_klass(hs.NewHandle((*f)->GetDeclaringClass())); - if (UNLIKELY(!Runtime::Current()->GetClassLinker()->EnsureInitialized(h_klass, true, true))) { - DCHECK(soa.Self()->IsExceptionPending()); - *class_or_rcvr = nullptr; - return false; + 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::Class> h_klass(hs.NewHandleWrapper(&declaringClass)); + if (UNLIKELY(!class_linker->EnsureInitialized(h_klass, true, true))) { + DCHECK(soa.Self()->IsExceptionPending()); + return false; + } } - *class_or_rcvr = h_klass.Get(); + *class_or_rcvr = declaringClass; return true; } - *class_or_rcvr = soa.Decode<mirror::Object*>(j_rcvr); - mirror::Class* declaringClass = (*f)->GetDeclaringClass(); if (!VerifyObjectIsClass(*class_or_rcvr, declaringClass)) { DCHECK(soa.Self()->IsExceptionPending()); - *class_or_rcvr = nullptr; return false; } return true; @@ -125,7 +129,7 @@ static jobject Field_get(JNIEnv* env, jobject javaField, jobject javaObj, jboole return nullptr; } // If field is not set to be accessible, verify it can be accessed by the caller. - if ((accessible == JNI_FALSE) && !VerifyFieldAccess(f, o, false)) { + if ((accessible == JNI_FALSE) && !VerifyFieldAccess<false>(soa.Self(), f, o)) { DCHECK(soa.Self()->IsExceptionPending()); return nullptr; } @@ -133,15 +137,16 @@ static jobject Field_get(JNIEnv* env, jobject javaField, jobject javaObj, jboole // Get the field's value, boxing if necessary. Primitive::Type field_type = f->GetTypeAsPrimitiveType(); JValue value; - if (!GetFieldValue(soa, o, f, field_type, true, &value)) { + if (!GetFieldValue<true>(soa, o, f, field_type, &value)) { DCHECK(soa.Self()->IsExceptionPending()); return nullptr; } return soa.AddLocalReference<jobject>(BoxPrimitive(field_type, value)); } -static JValue GetPrimitiveField(JNIEnv* env, jobject javaField, jobject javaObj, - char dst_descriptor, jboolean accessible) { +template<Primitive::Type kPrimitiveType> +ALWAYS_INLINE inline static JValue GetPrimitiveField(JNIEnv* env, jobject javaField, + jobject javaObj, jboolean accessible) { ScopedFastNativeObjectAccess soa(env); mirror::ArtField* f = mirror::ArtField::FromReflectedField(soa, javaField); mirror::Object* o = nullptr; @@ -151,7 +156,7 @@ static JValue GetPrimitiveField(JNIEnv* env, jobject javaField, jobject javaObj, } // If field is not set to be accessible, verify it can be accessed by the caller. - if ((accessible == JNI_FALSE) && !VerifyFieldAccess(f, o, false)) { + if (accessible == JNI_FALSE && !VerifyFieldAccess<false>(soa.Self(), f, o)) { DCHECK(soa.Self()->IsExceptionPending()); return JValue(); } @@ -160,15 +165,22 @@ static JValue GetPrimitiveField(JNIEnv* env, jobject javaField, jobject javaObj, // Read the value. Primitive::Type field_type = f->GetTypeAsPrimitiveType(); JValue field_value; - if (!GetFieldValue(soa, o, f, field_type, false, &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(NULL, false, field_type, Primitive::GetType(dst_descriptor), - field_value, &wide_value)) { + if (!ConvertPrimitiveValue(nullptr, false, field_type, kPrimitiveType, field_value, + &wide_value)) { DCHECK(soa.Self()->IsExceptionPending()); return JValue(); } @@ -177,36 +189,36 @@ static JValue GetPrimitiveField(JNIEnv* env, jobject javaField, jobject javaObj, static jboolean Field_getBoolean(JNIEnv* env, jobject javaField, jobject javaObj, jboolean accessible) { - return GetPrimitiveField(env, javaField, javaObj, 'Z', accessible).GetZ(); + return GetPrimitiveField<Primitive::kPrimBoolean>(env, javaField, javaObj, accessible).GetZ(); } static jbyte Field_getByte(JNIEnv* env, jobject javaField, jobject javaObj, jboolean accessible) { - return GetPrimitiveField(env, javaField, javaObj, 'B', accessible).GetB(); + return GetPrimitiveField<Primitive::kPrimByte>(env, javaField, javaObj, accessible).GetB(); } static jchar Field_getChar(JNIEnv* env, jobject javaField, jobject javaObj, jboolean accessible) { - return GetPrimitiveField(env, javaField, javaObj, 'C', accessible).GetC(); + return GetPrimitiveField<Primitive::kPrimChar>(env, javaField, javaObj, accessible).GetC(); } static jdouble Field_getDouble(JNIEnv* env, jobject javaField, jobject javaObj, jboolean accessible) { - return GetPrimitiveField(env, javaField, javaObj, 'D', accessible).GetD(); + return GetPrimitiveField<Primitive::kPrimDouble>(env, javaField, javaObj, accessible).GetD(); } static jfloat Field_getFloat(JNIEnv* env, jobject javaField, jobject javaObj, jboolean accessible) { - return GetPrimitiveField(env, javaField, javaObj, 'F', accessible).GetF(); + return GetPrimitiveField<Primitive::kPrimFloat>(env, javaField, javaObj, accessible).GetF(); } static jint Field_getInt(JNIEnv* env, jobject javaField, jobject javaObj, jboolean accessible) { - return GetPrimitiveField(env, javaField, javaObj, 'I', accessible).GetI(); + return GetPrimitiveField<Primitive::kPrimInt>(env, javaField, javaObj, accessible).GetI(); } static jlong Field_getLong(JNIEnv* env, jobject javaField, jobject javaObj, jboolean accessible) { - return GetPrimitiveField(env, javaField, javaObj, 'J', accessible).GetJ(); + return GetPrimitiveField<Primitive::kPrimLong>(env, javaField, javaObj, accessible).GetJ(); } static jshort Field_getShort(JNIEnv* env, jobject javaField, jobject javaObj, jboolean accessible) { - return GetPrimitiveField(env, javaField, javaObj, 'S', accessible).GetS(); + return GetPrimitiveField<Primitive::kPrimShort>(env, javaField, javaObj, accessible).GetS(); } static void SetFieldValue(ScopedFastNativeObjectAccess& soa, mirror::Object* o, @@ -289,14 +301,15 @@ static void Field_set(JNIEnv* env, jobject javaField, jobject javaObj, jobject j return; } // If field is not set to be accessible, verify it can be accessed by the caller. - if ((accessible == JNI_FALSE) && !VerifyFieldAccess(f, o, true)) { + if ((accessible == JNI_FALSE) && !VerifyFieldAccess<true>(soa.Self(), f, o)) { DCHECK(soa.Self()->IsExceptionPending()); return; } SetFieldValue(soa, o, f, field_prim_type, true, unboxed_value); } -static void SetPrimitiveField(JNIEnv* env, jobject javaField, jobject javaObj, char src_descriptor, +template<Primitive::Type kPrimitiveType> +static void SetPrimitiveField(JNIEnv* env, jobject javaField, jobject javaObj, const JValue& new_value, jboolean accessible) { ScopedFastNativeObjectAccess soa(env); mirror::ArtField* f = mirror::ArtField::FromReflectedField(soa, javaField); @@ -313,14 +326,13 @@ static void SetPrimitiveField(JNIEnv* env, jobject javaField, jobject javaObj, c // Widen the value if necessary (and possible). JValue wide_value; - if (!ConvertPrimitiveValue(nullptr, false, Primitive::GetType(src_descriptor), - field_type, new_value, &wide_value)) { + if (!ConvertPrimitiveValue(nullptr, 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 ((accessible == JNI_FALSE) && !VerifyFieldAccess(f, o, true)) { + if ((accessible == JNI_FALSE) && !VerifyFieldAccess<true>(soa.Self(), f, o)) { DCHECK(soa.Self()->IsExceptionPending()); return; } @@ -333,56 +345,56 @@ static void Field_setBoolean(JNIEnv* env, jobject javaField, jobject javaObj, jb jboolean accessible) { JValue value; value.SetZ(z); - SetPrimitiveField(env, javaField, javaObj, 'Z', value, accessible); + SetPrimitiveField<Primitive::kPrimBoolean>(env, javaField, javaObj, value, accessible); } static void Field_setByte(JNIEnv* env, jobject javaField, jobject javaObj, jbyte b, jboolean accessible) { JValue value; value.SetB(b); - SetPrimitiveField(env, javaField, javaObj, 'B', value, accessible); + SetPrimitiveField<Primitive::kPrimByte>(env, javaField, javaObj, value, accessible); } static void Field_setChar(JNIEnv* env, jobject javaField, jobject javaObj, jchar c, jboolean accessible) { JValue value; value.SetC(c); - SetPrimitiveField(env, javaField, javaObj, 'C', value, accessible); + SetPrimitiveField<Primitive::kPrimChar>(env, javaField, javaObj, value, accessible); } static void Field_setDouble(JNIEnv* env, jobject javaField, jobject javaObj, jdouble d, jboolean accessible) { JValue value; value.SetD(d); - SetPrimitiveField(env, javaField, javaObj, 'D', value, accessible); + SetPrimitiveField<Primitive::kPrimDouble>(env, javaField, javaObj, value, accessible); } static void Field_setFloat(JNIEnv* env, jobject javaField, jobject javaObj, jfloat f, jboolean accessible) { JValue value; value.SetF(f); - SetPrimitiveField(env, javaField, javaObj, 'F', value, accessible); + SetPrimitiveField<Primitive::kPrimFloat>(env, javaField, javaObj, value, accessible); } static void Field_setInt(JNIEnv* env, jobject javaField, jobject javaObj, jint i, jboolean accessible) { JValue value; value.SetI(i); - SetPrimitiveField(env, javaField, javaObj, 'I', value, accessible); + SetPrimitiveField<Primitive::kPrimInt>(env, javaField, javaObj, value, accessible); } static void Field_setLong(JNIEnv* env, jobject javaField, jobject javaObj, jlong j, jboolean accessible) { JValue value; value.SetJ(j); - SetPrimitiveField(env, javaField, javaObj, 'J', value, accessible); + SetPrimitiveField<Primitive::kPrimLong>(env, javaField, javaObj, value, accessible); } static void Field_setShort(JNIEnv* env, jobject javaField, jobject javaObj, jshort s, jboolean accessible) { JValue value; value.SetS(s); - SetPrimitiveField(env, javaField, javaObj, 'S', value, accessible); + SetPrimitiveField<Primitive::kPrimShort>(env, javaField, javaObj, value, accessible); } static JNINativeMethod gMethods[] = { diff --git a/runtime/reflection-inl.h b/runtime/reflection-inl.h new file mode 100644 index 0000000000..be4d5603f9 --- /dev/null +++ b/runtime/reflection-inl.h @@ -0,0 +1,106 @@ +/* + * 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_REFLECTION_INL_H_ +#define ART_RUNTIME_REFLECTION_INL_H_ + +#include "reflection.h" + +#include "base/stringprintf.h" +#include "common_throws.h" +#include "jvalue.h" +#include "primitive.h" +#include "utils.h" + +namespace art { + +inline bool ConvertPrimitiveValue(const ThrowLocation* throw_location, bool unbox_for_result, + Primitive::Type srcType, Primitive::Type dstType, + const JValue& src, JValue* dst) { + DCHECK(srcType != Primitive::kPrimNot && dstType != Primitive::kPrimNot); + if (LIKELY(srcType == dstType)) { + dst->SetJ(src.GetJ()); + return true; + } + switch (dstType) { + case Primitive::kPrimBoolean: // Fall-through. + case Primitive::kPrimChar: // Fall-through. + case Primitive::kPrimByte: + // Only expect assignment with source and destination of identical type. + break; + case Primitive::kPrimShort: + if (srcType == Primitive::kPrimByte) { + dst->SetS(src.GetI()); + return true; + } + break; + case Primitive::kPrimInt: + if (srcType == Primitive::kPrimByte || srcType == Primitive::kPrimChar || + srcType == Primitive::kPrimShort) { + dst->SetI(src.GetI()); + return true; + } + break; + case Primitive::kPrimLong: + if (srcType == Primitive::kPrimByte || srcType == Primitive::kPrimChar || + srcType == Primitive::kPrimShort || srcType == Primitive::kPrimInt) { + dst->SetJ(src.GetI()); + return true; + } + break; + case Primitive::kPrimFloat: + if (srcType == Primitive::kPrimByte || srcType == Primitive::kPrimChar || + srcType == Primitive::kPrimShort || srcType == Primitive::kPrimInt) { + dst->SetF(src.GetI()); + return true; + } else if (srcType == Primitive::kPrimLong) { + dst->SetF(src.GetJ()); + return true; + } + break; + case Primitive::kPrimDouble: + if (srcType == Primitive::kPrimByte || srcType == Primitive::kPrimChar || + srcType == Primitive::kPrimShort || srcType == Primitive::kPrimInt) { + dst->SetD(src.GetI()); + return true; + } else if (srcType == Primitive::kPrimLong) { + dst->SetD(src.GetJ()); + return true; + } else if (srcType == Primitive::kPrimFloat) { + dst->SetD(src.GetF()); + return true; + } + break; + default: + break; + } + if (!unbox_for_result) { + ThrowIllegalArgumentException(throw_location, + StringPrintf("Invalid primitive conversion from %s to %s", + PrettyDescriptor(srcType).c_str(), + PrettyDescriptor(dstType).c_str()).c_str()); + } else { + ThrowClassCastException(throw_location, + StringPrintf("Couldn't convert result of type %s to %s", + PrettyDescriptor(srcType).c_str(), + PrettyDescriptor(dstType).c_str()).c_str()); + } + return false; +} + +} // namespace art + +#endif // ART_RUNTIME_REFLECTION_INL_H_ diff --git a/runtime/reflection.cc b/runtime/reflection.cc index 4cd61a5305..18fcee4381 100644 --- a/runtime/reflection.cc +++ b/runtime/reflection.cc @@ -14,7 +14,7 @@ * limitations under the License. */ -#include "reflection.h" +#include "reflection-inl.h" #include "class_linker.h" #include "common_throws.h" @@ -565,7 +565,7 @@ jobject InvokeMethod(const ScopedObjectAccessAlreadyRunnable& soa, jobject javaM } // If method is not set to be accessible, verify it can be accessed by the caller. - if (!accessible && !VerifyAccess(receiver, declaring_class, m->GetAccessFlags())) { + if (!accessible && !VerifyAccess(soa.Self(), receiver, declaring_class, m->GetAccessFlags())) { ThrowIllegalAccessException(nullptr, StringPrintf("Cannot access method: %s", PrettyMethod(m).c_str()).c_str()); return nullptr; @@ -617,84 +617,6 @@ bool VerifyObjectIsClass(mirror::Object* o, mirror::Class* c) { return true; } -static std::string PrettyDescriptor(Primitive::Type type) { - return PrettyDescriptor(Primitive::Descriptor(type)); -} - -bool ConvertPrimitiveValue(const ThrowLocation* throw_location, bool unbox_for_result, - Primitive::Type srcType, Primitive::Type dstType, - const JValue& src, JValue* dst) { - DCHECK(srcType != Primitive::kPrimNot && dstType != Primitive::kPrimNot); - if (LIKELY(srcType == dstType)) { - dst->SetJ(src.GetJ()); - return true; - } - switch (dstType) { - case Primitive::kPrimBoolean: // Fall-through. - case Primitive::kPrimChar: // Fall-through. - case Primitive::kPrimByte: - // Only expect assignment with source and destination of identical type. - break; - case Primitive::kPrimShort: - if (srcType == Primitive::kPrimByte) { - dst->SetS(src.GetI()); - return true; - } - break; - case Primitive::kPrimInt: - if (srcType == Primitive::kPrimByte || srcType == Primitive::kPrimChar || - srcType == Primitive::kPrimShort) { - dst->SetI(src.GetI()); - return true; - } - break; - case Primitive::kPrimLong: - if (srcType == Primitive::kPrimByte || srcType == Primitive::kPrimChar || - srcType == Primitive::kPrimShort || srcType == Primitive::kPrimInt) { - dst->SetJ(src.GetI()); - return true; - } - break; - case Primitive::kPrimFloat: - if (srcType == Primitive::kPrimByte || srcType == Primitive::kPrimChar || - srcType == Primitive::kPrimShort || srcType == Primitive::kPrimInt) { - dst->SetF(src.GetI()); - return true; - } else if (srcType == Primitive::kPrimLong) { - dst->SetF(src.GetJ()); - return true; - } - break; - case Primitive::kPrimDouble: - if (srcType == Primitive::kPrimByte || srcType == Primitive::kPrimChar || - srcType == Primitive::kPrimShort || srcType == Primitive::kPrimInt) { - dst->SetD(src.GetI()); - return true; - } else if (srcType == Primitive::kPrimLong) { - dst->SetD(src.GetJ()); - return true; - } else if (srcType == Primitive::kPrimFloat) { - dst->SetD(src.GetF()); - return true; - } - break; - default: - break; - } - if (!unbox_for_result) { - ThrowIllegalArgumentException(throw_location, - StringPrintf("Invalid primitive conversion from %s to %s", - PrettyDescriptor(srcType).c_str(), - PrettyDescriptor(dstType).c_str()).c_str()); - } else { - ThrowClassCastException(throw_location, - StringPrintf("Couldn't convert result of type %s to %s", - PrettyDescriptor(srcType).c_str(), - PrettyDescriptor(dstType).c_str()).c_str()); - } - return false; -} - mirror::Object* BoxPrimitive(Primitive::Type src_class, const JValue& value) { if (src_class == Primitive::kPrimNot) { return value.GetL(); @@ -866,16 +788,18 @@ bool UnboxPrimitiveForResult(const ThrowLocation& throw_location, mirror::Object return UnboxPrimitive(&throw_location, o, dst_class, nullptr, unboxed_value); } -bool VerifyAccess(mirror::Object* obj, mirror::Class* declaring_class, uint32_t access_flags) { - NthCallerVisitor visitor(Thread::Current(), 2); +bool VerifyAccess(Thread* self, mirror::Object* obj, mirror::Class* declaring_class, uint32_t access_flags) { + if ((access_flags & kAccPublic) != 0) { + return true; + } + NthCallerVisitor visitor(self, 2); visitor.WalkStack(); if (UNLIKELY(visitor.caller == nullptr)) { // The caller is an attached native thread. - return (access_flags & kAccPublic) != 0; + return false; } mirror::Class* caller_class = visitor.caller->GetDeclaringClass(); - - if (((access_flags & kAccPublic) != 0) || (caller_class == declaring_class)) { + if (caller_class == declaring_class) { return true; } if ((access_flags & kAccPrivate) != 0) { @@ -889,10 +813,7 @@ bool VerifyAccess(mirror::Object* obj, mirror::Class* declaring_class, uint32_t return true; } } - if (!declaring_class->IsInSamePackage(caller_class)) { - return false; - } - return true; + return declaring_class->IsInSamePackage(caller_class); } } // namespace art diff --git a/runtime/reflection.h b/runtime/reflection.h index 2c54c067fd..0f41aca85c 100644 --- a/runtime/reflection.h +++ b/runtime/reflection.h @@ -42,9 +42,9 @@ bool UnboxPrimitiveForResult(const ThrowLocation& throw_location, mirror::Object mirror::Class* dst_class, JValue* unboxed_value) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); -bool ConvertPrimitiveValue(const ThrowLocation* throw_location, bool unbox_for_result, - Primitive::Type src_class, Primitive::Type dst_class, - const JValue& src, JValue* dst) +ALWAYS_INLINE bool ConvertPrimitiveValue(const ThrowLocation* throw_location, bool unbox_for_result, + Primitive::Type src_class, Primitive::Type dst_class, + const JValue& src, JValue* dst) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); JValue InvokeWithVarArgs(const ScopedObjectAccessAlreadyRunnable& soa, jobject obj, jmethodID mid, @@ -74,7 +74,8 @@ jobject InvokeMethod(const ScopedObjectAccessAlreadyRunnable& soa, jobject metho bool VerifyObjectIsClass(mirror::Object* o, mirror::Class* c) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); -bool VerifyAccess(mirror::Object* obj, mirror::Class* declaring_class, uint32_t access_flags) +bool VerifyAccess(Thread* self, mirror::Object* obj, mirror::Class* declaring_class, + uint32_t access_flags) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); } // namespace art diff --git a/runtime/utils.cc b/runtime/utils.cc index d01c2cb7fc..376575918f 100644 --- a/runtime/utils.cc +++ b/runtime/utils.cc @@ -1376,4 +1376,8 @@ bool Exec(std::vector<std::string>& arg_vector, std::string* error_msg) { return true; } +std::string PrettyDescriptor(Primitive::Type type) { + return PrettyDescriptor(Primitive::Descriptor(type)); +} + } // namespace art diff --git a/runtime/utils.h b/runtime/utils.h index 1dfa02a369..5bdbba8909 100644 --- a/runtime/utils.h +++ b/runtime/utils.h @@ -25,9 +25,10 @@ #include <vector> #include "base/logging.h" +#include "base/mutex.h" #include "globals.h" #include "instruction_set.h" -#include "base/mutex.h" +#include "primitive.h" #ifdef HAVE_ANDROID_OS #include "cutils/properties.h" @@ -280,6 +281,7 @@ std::string PrettyDescriptor(mirror::String* descriptor) std::string PrettyDescriptor(const char* descriptor); std::string PrettyDescriptor(mirror::Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); +std::string PrettyDescriptor(Primitive::Type type); // Returns a human-readable signature for 'f'. Something like "a.b.C.f" or // "int a.b.C.f" (depending on the value of 'with_type'). diff --git a/runtime/utils_test.cc b/runtime/utils_test.cc index d6c90e1d45..1b2c3eec05 100644 --- a/runtime/utils_test.cc +++ b/runtime/utils_test.cc @@ -44,6 +44,18 @@ TEST_F(UtilsTest, PrettyDescriptor_ScalarReferences) { EXPECT_EQ("java.lang.String", PrettyDescriptor("Ljava/lang/String;")); } +TEST_F(UtilsTest, PrettyDescriptor_Primitive) { + EXPECT_EQ("boolean", PrettyDescriptor(Primitive::kPrimBoolean)); + EXPECT_EQ("byte", PrettyDescriptor(Primitive::kPrimByte)); + EXPECT_EQ("char", PrettyDescriptor(Primitive::kPrimChar)); + EXPECT_EQ("short", PrettyDescriptor(Primitive::kPrimShort)); + EXPECT_EQ("int", PrettyDescriptor(Primitive::kPrimInt)); + EXPECT_EQ("float", PrettyDescriptor(Primitive::kPrimFloat)); + EXPECT_EQ("long", PrettyDescriptor(Primitive::kPrimLong)); + EXPECT_EQ("double", PrettyDescriptor(Primitive::kPrimDouble)); + EXPECT_EQ("void", PrettyDescriptor(Primitive::kPrimVoid)); +} + TEST_F(UtilsTest, PrettyDescriptor_PrimitiveArrays) { EXPECT_EQ("boolean[]", PrettyDescriptor("[Z")); EXPECT_EQ("boolean[][]", PrettyDescriptor("[[Z")); |