ART: Add GetSignatureAnnotation to unstarted runtime
Add support for Class.getSignatureAnnotation to the unstarted
runtime. Refactor dex file annotation code to support transactions.
Bug: 34956610
Test: m
Test: m test-art-host-gtest-unstarted_runtime_test
Test: Device boots
Change-Id: I9f4a93e05ad6999c46c3bb1dbabe48a1ad6225b2
diff --git a/runtime/dex_file_annotations.cc b/runtime/dex_file_annotations.cc
index a95f94c..d39ea35 100644
--- a/runtime/dex_file_annotations.cc
+++ b/runtime/dex_file_annotations.cc
@@ -299,6 +299,7 @@
return result.GetL();
}
+template <bool kTransactionActive>
bool ProcessAnnotationValue(Handle<mirror::Class> klass,
const uint8_t** annotation_ptr,
DexFile::AnnotationValue* annotation_value,
@@ -409,22 +410,21 @@
}
PointerSize pointer_size = class_linker->GetImagePointerSize();
set_object = true;
- DCHECK(!Runtime::Current()->IsActiveTransaction());
if (method->IsConstructor()) {
if (pointer_size == PointerSize::k64) {
element_object = mirror::Constructor::CreateFromArtMethod<PointerSize::k64,
- false>(self, method);
+ kTransactionActive>(self, method);
} else {
element_object = mirror::Constructor::CreateFromArtMethod<PointerSize::k32,
- false>(self, method);
+ kTransactionActive>(self, method);
}
} else {
if (pointer_size == PointerSize::k64) {
element_object = mirror::Method::CreateFromArtMethod<PointerSize::k64,
- false>(self, method);
+ kTransactionActive>(self, method);
} else {
element_object = mirror::Method::CreateFromArtMethod<PointerSize::k32,
- false>(self, method);
+ kTransactionActive>(self, method);
}
}
if (element_object == nullptr) {
@@ -449,9 +449,11 @@
set_object = true;
PointerSize pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize();
if (pointer_size == PointerSize::k64) {
- element_object = mirror::Field::CreateFromArtField<PointerSize::k64>(self, field, true);
+ element_object = mirror::Field::CreateFromArtField<PointerSize::k64,
+ kTransactionActive>(self, field, true);
} else {
- element_object = mirror::Field::CreateFromArtField<PointerSize::k32>(self, field, true);
+ element_object = mirror::Field::CreateFromArtField<PointerSize::k32,
+ kTransactionActive>(self, field, true);
}
if (element_object == nullptr) {
return false;
@@ -497,45 +499,49 @@
}
DexFile::AnnotationValue new_annotation_value;
for (uint32_t i = 0; i < size; ++i) {
- if (!ProcessAnnotationValue(klass, &annotation, &new_annotation_value,
- component_type, DexFile::kPrimitivesOrObjects)) {
+ if (!ProcessAnnotationValue<kTransactionActive>(klass,
+ &annotation,
+ &new_annotation_value,
+ component_type,
+ DexFile::kPrimitivesOrObjects)) {
return false;
}
if (!component_type->IsPrimitive()) {
mirror::Object* obj = new_annotation_value.value_.GetL();
- new_array->AsObjectArray<mirror::Object>()->SetWithoutChecks<false>(i, obj);
+ new_array->AsObjectArray<mirror::Object>()->
+ SetWithoutChecks<kTransactionActive>(i, obj);
} else {
switch (new_annotation_value.type_) {
case DexFile::kDexAnnotationByte:
- new_array->AsByteArray()->SetWithoutChecks<false>(
+ new_array->AsByteArray()->SetWithoutChecks<kTransactionActive>(
i, new_annotation_value.value_.GetB());
break;
case DexFile::kDexAnnotationShort:
- new_array->AsShortArray()->SetWithoutChecks<false>(
+ new_array->AsShortArray()->SetWithoutChecks<kTransactionActive>(
i, new_annotation_value.value_.GetS());
break;
case DexFile::kDexAnnotationChar:
- new_array->AsCharArray()->SetWithoutChecks<false>(
+ new_array->AsCharArray()->SetWithoutChecks<kTransactionActive>(
i, new_annotation_value.value_.GetC());
break;
case DexFile::kDexAnnotationInt:
- new_array->AsIntArray()->SetWithoutChecks<false>(
+ new_array->AsIntArray()->SetWithoutChecks<kTransactionActive>(
i, new_annotation_value.value_.GetI());
break;
case DexFile::kDexAnnotationLong:
- new_array->AsLongArray()->SetWithoutChecks<false>(
+ new_array->AsLongArray()->SetWithoutChecks<kTransactionActive>(
i, new_annotation_value.value_.GetJ());
break;
case DexFile::kDexAnnotationFloat:
- new_array->AsFloatArray()->SetWithoutChecks<false>(
+ new_array->AsFloatArray()->SetWithoutChecks<kTransactionActive>(
i, new_annotation_value.value_.GetF());
break;
case DexFile::kDexAnnotationDouble:
- new_array->AsDoubleArray()->SetWithoutChecks<false>(
+ new_array->AsDoubleArray()->SetWithoutChecks<kTransactionActive>(
i, new_annotation_value.value_.GetD());
break;
case DexFile::kDexAnnotationBoolean:
- new_array->AsBooleanArray()->SetWithoutChecks<false>(
+ new_array->AsBooleanArray()->SetWithoutChecks<kTransactionActive>(
i, new_annotation_value.value_.GetZ());
break;
default:
@@ -611,8 +617,11 @@
annotation_method->GetReturnType(true /* resolve */)));
DexFile::AnnotationValue annotation_value;
- if (!ProcessAnnotationValue(klass, annotation, &annotation_value, method_return,
- DexFile::kAllObjects)) {
+ if (!ProcessAnnotationValue<false>(klass,
+ annotation,
+ &annotation_value,
+ method_return,
+ DexFile::kAllObjects)) {
return nullptr;
}
Handle<mirror::Object> value_object(hs.NewHandle(annotation_value.value_.GetL()));
@@ -716,8 +725,18 @@
return nullptr;
}
DexFile::AnnotationValue annotation_value;
- if (!ProcessAnnotationValue(klass, &annotation, &annotation_value, array_class,
- DexFile::kAllObjects)) {
+ bool result = Runtime::Current()->IsActiveTransaction()
+ ? ProcessAnnotationValue<true>(klass,
+ &annotation,
+ &annotation_value,
+ array_class,
+ DexFile::kAllObjects)
+ : ProcessAnnotationValue<false>(klass,
+ &annotation,
+ &annotation_value,
+ array_class,
+ DexFile::kAllObjects);
+ if (!result) {
return nullptr;
}
if (annotation_value.type_ != expected_type) {
@@ -949,8 +968,11 @@
StackHandleScope<2> hs(Thread::Current());
Handle<mirror::Class> h_klass(hs.NewHandle(klass));
Handle<mirror::Class> return_type(hs.NewHandle(method->GetReturnType(true /* resolve */)));
- if (!ProcessAnnotationValue(h_klass, &annotation, &annotation_value, return_type,
- DexFile::kAllObjects)) {
+ if (!ProcessAnnotationValue<false>(h_klass,
+ &annotation,
+ &annotation_value,
+ return_type,
+ DexFile::kAllObjects)) {
return nullptr;
}
return annotation_value.value_.GetL();
@@ -1201,8 +1223,11 @@
return nullptr;
}
DexFile::AnnotationValue annotation_value;
- if (!ProcessAnnotationValue(klass, &annotation, &annotation_value,
- ScopedNullHandle<mirror::Class>(), DexFile::kAllRaw)) {
+ if (!ProcessAnnotationValue<false>(klass,
+ &annotation,
+ &annotation_value,
+ ScopedNullHandle<mirror::Class>(),
+ DexFile::kAllRaw)) {
return nullptr;
}
if (annotation_value.type_ != DexFile::kDexAnnotationMethod) {
@@ -1252,9 +1277,11 @@
return false;
}
DexFile::AnnotationValue annotation_value;
- if (!ProcessAnnotationValue(klass, &annotation, &annotation_value,
- ScopedNullHandle<mirror::Class>(),
- DexFile::kAllObjects)) {
+ if (!ProcessAnnotationValue<false>(klass,
+ &annotation,
+ &annotation_value,
+ ScopedNullHandle<mirror::Class>(),
+ DexFile::kAllObjects)) {
return false;
}
if (annotation_value.type_ != DexFile::kDexAnnotationNull &&
@@ -1283,8 +1310,11 @@
return false;
}
DexFile::AnnotationValue annotation_value;
- if (!ProcessAnnotationValue(klass, &annotation, &annotation_value,
- ScopedNullHandle<mirror::Class>(), DexFile::kAllRaw)) {
+ if (!ProcessAnnotationValue<false>(klass,
+ &annotation,
+ &annotation_value,
+ ScopedNullHandle<mirror::Class>(),
+ DexFile::kAllRaw)) {
return false;
}
if (annotation_value.type_ != DexFile::kDexAnnotationInt) {
diff --git a/runtime/interpreter/unstarted_runtime.cc b/runtime/interpreter/unstarted_runtime.cc
index fc21945..4a321e6 100644
--- a/runtime/interpreter/unstarted_runtime.cc
+++ b/runtime/interpreter/unstarted_runtime.cc
@@ -445,6 +445,20 @@
result->SetI(mirror::Class::GetInnerClassFlags(klass, default_value));
}
+void UnstartedRuntime::UnstartedClassGetSignatureAnnotation(
+ Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
+ StackHandleScope<1> hs(self);
+ Handle<mirror::Class> klass(hs.NewHandle(
+ reinterpret_cast<mirror::Class*>(shadow_frame->GetVRegReference(arg_offset))));
+
+ if (klass->IsProxyClass() || klass->GetDexCache() == nullptr) {
+ result->SetL(nullptr);
+ return;
+ }
+
+ result->SetL(annotations::GetSignatureAnnotationForClass(klass));
+}
+
void UnstartedRuntime::UnstartedClassIsAnonymousClass(
Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
StackHandleScope<1> hs(self);
diff --git a/runtime/interpreter/unstarted_runtime_list.h b/runtime/interpreter/unstarted_runtime_list.h
index 929b747..c6114da 100644
--- a/runtime/interpreter/unstarted_runtime_list.h
+++ b/runtime/interpreter/unstarted_runtime_list.h
@@ -31,6 +31,7 @@
V(ClassGetDeclaringClass, "java.lang.Class java.lang.Class.getDeclaringClass()") \
V(ClassGetEnclosingClass, "java.lang.Class java.lang.Class.getEnclosingClass()") \
V(ClassGetInnerClassFlags, "int java.lang.Class.getInnerClassFlags(int)") \
+ V(ClassGetSignatureAnnotation, "java.lang.String[] java.lang.Class.getSignatureAnnotation()") \
V(ClassIsAnonymousClass, "boolean java.lang.Class.isAnonymousClass()") \
V(ClassLoaderGetResourceAsStream, "java.io.InputStream java.lang.ClassLoader.getResourceAsStream(java.lang.String)") \
V(VmClassLoaderFindLoadedClass, "java.lang.Class java.lang.VMClassLoader.findLoadedClass(java.lang.ClassLoader, java.lang.String)") \
diff --git a/runtime/interpreter/unstarted_runtime_test.cc b/runtime/interpreter/unstarted_runtime_test.cc
index 3a0d0e7..4186c37 100644
--- a/runtime/interpreter/unstarted_runtime_test.cc
+++ b/runtime/interpreter/unstarted_runtime_test.cc
@@ -29,6 +29,8 @@
#include "handle_scope-inl.h"
#include "interpreter/interpreter_common.h"
#include "mirror/class_loader.h"
+#include "mirror/object_array-inl.h"
+#include "mirror/object-inl.h"
#include "mirror/string-inl.h"
#include "runtime.h"
#include "scoped_thread_state_change-inl.h"
@@ -1077,9 +1079,9 @@
StackHandleScope<1> hs(self);
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
Handle<mirror::Class> log_manager_class = hs.NewHandle(
- class_linker->FindClass(self,
- "Ljava/util/logging/LogManager;",
- ScopedNullHandle<mirror::ClassLoader>()));
+ class_linker->FindClass(self,
+ "Ljava/util/logging/LogManager;",
+ ScopedNullHandle<mirror::ClassLoader>()));
ASSERT_TRUE(log_manager_class.Get() != nullptr);
ASSERT_TRUE(class_linker->EnsureInitialized(self, log_manager_class, true, true));
}
@@ -1278,5 +1280,42 @@
RunTest(runner, true, false);
}
+TEST_F(UnstartedRuntimeTest, ClassGetSignatureAnnotation) {
+ Thread* self = Thread::Current();
+ ScopedObjectAccess soa(self);
+
+ StackHandleScope<1> hs(self);
+ ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+ Handle<mirror::Class> list_class = hs.NewHandle(
+ class_linker->FindClass(self,
+ "Ljava/util/List;",
+ ScopedNullHandle<mirror::ClassLoader>()));
+ ASSERT_TRUE(list_class.Get() != nullptr);
+ ASSERT_TRUE(class_linker->EnsureInitialized(self, list_class, true, true));
+
+ JValue result;
+ ShadowFrame* shadow_frame = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, nullptr, 0);
+
+ shadow_frame->SetVRegReference(0, list_class.Get());
+ UnstartedClassGetSignatureAnnotation(self, shadow_frame, &result, 0);
+ ASSERT_TRUE(result.GetL() != nullptr);
+ ASSERT_FALSE(self->IsExceptionPending());
+
+ ShadowFrame::DeleteDeoptimizedFrame(shadow_frame);
+
+ ASSERT_TRUE(result.GetL()->IsObjectArray());
+ ObjPtr<mirror::ObjectArray<mirror::Object>> array =
+ result.GetL()->AsObjectArray<mirror::Object>();
+ std::ostringstream oss;
+ for (int32_t i = 0; i != array->GetLength(); ++i) {
+ ObjPtr<mirror::Object> elem = array->Get(i);
+ ASSERT_TRUE(elem != nullptr);
+ ASSERT_TRUE(elem->IsString());
+ oss << elem->AsString()->ToModifiedUtf8();
+ }
+ std::string output_string = oss.str();
+ ASSERT_EQ(output_string, "<E:Ljava/lang/Object;>Ljava/lang/Object;Ljava/util/Collection<TE;>;");
+}
+
} // namespace interpreter
} // namespace art