Move mirror::ArtMethod to native
Optimizing + quick tests are passing, devices boot.
TODO: Test and fix bugs in mips64.
Saves 16 bytes per most ArtMethod, 7.5MB reduction in system PSS.
Some of the savings are from removal of virtual methods and direct
methods object arrays.
Bug: 19264997
Change-Id: I622469a0cfa0e7082a2119f3d6a9491eb61e3f3d
diff --git a/runtime/class_linker_test.cc b/runtime/class_linker_test.cc
index d155941..a4e0227 100644
--- a/runtime/class_linker_test.cc
+++ b/runtime/class_linker_test.cc
@@ -20,6 +20,7 @@
#include <string>
#include "art_field-inl.h"
+#include "art_method-inl.h"
#include "class_linker-inl.h"
#include "common_runtime_test.h"
#include "dex_file.h"
@@ -27,7 +28,6 @@
#include "gc/heap.h"
#include "mirror/abstract_method.h"
#include "mirror/accessible_object.h"
-#include "mirror/art_method-inl.h"
#include "mirror/class-inl.h"
#include "mirror/dex_cache.h"
#include "mirror/field.h"
@@ -159,9 +159,9 @@
EXPECT_EQ(class_linker_->FindArrayClass(self, &array_ptr), array.Get());
}
- void AssertMethod(mirror::ArtMethod* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ void AssertMethod(ArtMethod* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
EXPECT_TRUE(method != nullptr);
- EXPECT_TRUE(method->GetClass() != nullptr);
+ EXPECT_TRUE(method->GetDeclaringClass() != nullptr);
EXPECT_TRUE(method->GetName() != nullptr);
EXPECT_TRUE(method->GetSignature() != Signature::NoSignature());
@@ -208,8 +208,8 @@
if (klass->IsInterface()) {
EXPECT_TRUE(klass->IsAbstract());
if (klass->NumDirectMethods() == 1) {
- EXPECT_TRUE(klass->GetDirectMethod(0)->IsClassInitializer());
- EXPECT_TRUE(klass->GetDirectMethod(0)->IsDirect());
+ EXPECT_TRUE(klass->GetDirectMethod(0, sizeof(void*))->IsClassInitializer());
+ EXPECT_TRUE(klass->GetDirectMethod(0, sizeof(void*))->IsDirect());
} else {
EXPECT_EQ(0U, klass->NumDirectMethods());
}
@@ -246,18 +246,16 @@
EXPECT_FALSE(klass->IsPrimitive());
EXPECT_TRUE(klass->CanAccess(klass.Get()));
- for (size_t i = 0; i < klass->NumDirectMethods(); i++) {
- mirror::ArtMethod* method = klass->GetDirectMethod(i);
- AssertMethod(method);
- EXPECT_TRUE(method->IsDirect());
- EXPECT_EQ(klass.Get(), method->GetDeclaringClass());
+ for (ArtMethod& method : klass->GetDirectMethods(sizeof(void*))) {
+ AssertMethod(&method);
+ EXPECT_TRUE(method.IsDirect());
+ EXPECT_EQ(klass.Get(), method.GetDeclaringClass());
}
- for (size_t i = 0; i < klass->NumVirtualMethods(); i++) {
- mirror::ArtMethod* method = klass->GetVirtualMethod(i);
- AssertMethod(method);
- EXPECT_FALSE(method->IsDirect());
- EXPECT_TRUE(method->GetDeclaringClass()->IsAssignableFrom(klass.Get()));
+ for (ArtMethod& method : klass->GetVirtualMethods(sizeof(void*))) {
+ AssertMethod(&method);
+ EXPECT_FALSE(method.IsDirect());
+ EXPECT_TRUE(method.GetDeclaringClass()->IsAssignableFrom(klass.Get()));
}
for (size_t i = 0; i < klass->NumInstanceFields(); i++) {
@@ -358,9 +356,10 @@
class_linker_->VisitRoots(&visitor, kVisitRootFlagAllRoots);
// Verify the dex cache has resolution methods in all resolved method slots
mirror::DexCache* dex_cache = class_linker_->FindDexCache(dex);
- mirror::ObjectArray<mirror::ArtMethod>* resolved_methods = dex_cache->GetResolvedMethods();
+ auto* resolved_methods = dex_cache->GetResolvedMethods();
for (size_t i = 0; i < static_cast<size_t>(resolved_methods->GetLength()); i++) {
- EXPECT_TRUE(resolved_methods->Get(i) != nullptr) << dex.GetLocation() << " i=" << i;
+ EXPECT_TRUE(resolved_methods->GetElementPtrSize<ArtMethod*>(i, sizeof(void*)) != nullptr)
+ << dex.GetLocation() << " i=" << i;
}
}
@@ -394,9 +393,8 @@
bool error = false;
- // Methods and classes have a different size due to padding field. Strings are variable length.
- if (!klass->IsArtMethodClass() && !klass->IsClassClass() && !klass->IsStringClass() &&
- !is_static) {
+ // Classes have a different size due to padding field. Strings are variable length.
+ if (!klass->IsClassClass() && !klass->IsStringClass() && !is_static) {
// Currently only required for AccessibleObject since of the padding fields. The class linker
// says AccessibleObject is 9 bytes but sizeof(AccessibleObject) is 12 bytes due to padding.
// The RoundUp is to get around this case.
@@ -487,20 +485,6 @@
};
};
-struct ArtMethodOffsets : public CheckOffsets<mirror::ArtMethod> {
- ArtMethodOffsets() : CheckOffsets<mirror::ArtMethod>(false, "Ljava/lang/reflect/ArtMethod;") {
- addOffset(OFFSETOF_MEMBER(mirror::ArtMethod, access_flags_), "accessFlags");
- addOffset(OFFSETOF_MEMBER(mirror::ArtMethod, declaring_class_), "declaringClass");
- addOffset(OFFSETOF_MEMBER(mirror::ArtMethod, dex_cache_resolved_methods_),
- "dexCacheResolvedMethods");
- addOffset(OFFSETOF_MEMBER(mirror::ArtMethod, dex_cache_resolved_types_),
- "dexCacheResolvedTypes");
- addOffset(OFFSETOF_MEMBER(mirror::ArtMethod, dex_code_item_offset_), "dexCodeItemOffset");
- addOffset(OFFSETOF_MEMBER(mirror::ArtMethod, dex_method_index_), "dexMethodIndex");
- addOffset(OFFSETOF_MEMBER(mirror::ArtMethod, method_index_), "methodIndex");
- };
-};
-
struct ClassOffsets : public CheckOffsets<mirror::Class> {
ClassOffsets() : CheckOffsets<mirror::Class>(false, "Ljava/lang/Class;") {
addOffset(OFFSETOF_MEMBER(mirror::Class, access_flags_), "accessFlags");
@@ -516,12 +500,14 @@
addOffset(OFFSETOF_MEMBER(mirror::Class, ifields_), "iFields");
addOffset(OFFSETOF_MEMBER(mirror::Class, iftable_), "ifTable");
addOffset(OFFSETOF_MEMBER(mirror::Class, name_), "name");
+ addOffset(OFFSETOF_MEMBER(mirror::Class, num_direct_methods_), "numDirectMethods");
addOffset(OFFSETOF_MEMBER(mirror::Class, num_instance_fields_), "numInstanceFields");
addOffset(OFFSETOF_MEMBER(mirror::Class, num_reference_instance_fields_),
"numReferenceInstanceFields");
addOffset(OFFSETOF_MEMBER(mirror::Class, num_reference_static_fields_),
"numReferenceStaticFields");
addOffset(OFFSETOF_MEMBER(mirror::Class, num_static_fields_), "numStaticFields");
+ addOffset(OFFSETOF_MEMBER(mirror::Class, num_virtual_methods_), "numVirtualMethods");
addOffset(OFFSETOF_MEMBER(mirror::Class, object_size_), "objectSize");
addOffset(OFFSETOF_MEMBER(mirror::Class, primitive_type_), "primitiveType");
addOffset(OFFSETOF_MEMBER(mirror::Class, reference_instance_offsets_),
@@ -641,7 +627,6 @@
TEST_F(ClassLinkerTest, ValidateFieldOrderOfJavaCppUnionClasses) {
ScopedObjectAccess soa(Thread::Current());
EXPECT_TRUE(ObjectOffsets().Check());
- EXPECT_TRUE(ArtMethodOffsets().Check());
EXPECT_TRUE(ClassOffsets().Check());
EXPECT_TRUE(StringOffsets().Check());
EXPECT_TRUE(ThrowableOffsets().Check());
@@ -899,7 +884,7 @@
// Static final primitives that are initialized by a compile-time constant
// expression resolve to a copy of a constant value from the constant pool.
// So <clinit> should be null.
- mirror::ArtMethod* clinit = statics->FindDirectMethod("<clinit>", "()V");
+ ArtMethod* clinit = statics->FindDirectMethod("<clinit>", "()V", sizeof(void*));
EXPECT_TRUE(clinit == nullptr);
EXPECT_EQ(9U, statics->NumStaticFields());
@@ -986,15 +971,15 @@
EXPECT_TRUE(J->IsAssignableFrom(B.Get()));
const Signature void_sig = I->GetDexCache()->GetDexFile()->CreateSignature("()V");
- mirror::ArtMethod* Ii = I->FindVirtualMethod("i", void_sig);
- mirror::ArtMethod* Jj1 = J->FindVirtualMethod("j1", void_sig);
- mirror::ArtMethod* Jj2 = J->FindVirtualMethod("j2", void_sig);
- mirror::ArtMethod* Kj1 = K->FindInterfaceMethod("j1", void_sig);
- mirror::ArtMethod* Kj2 = K->FindInterfaceMethod("j2", void_sig);
- mirror::ArtMethod* Kk = K->FindInterfaceMethod("k", void_sig);
- mirror::ArtMethod* Ai = A->FindVirtualMethod("i", void_sig);
- mirror::ArtMethod* Aj1 = A->FindVirtualMethod("j1", void_sig);
- mirror::ArtMethod* Aj2 = A->FindVirtualMethod("j2", void_sig);
+ ArtMethod* Ii = I->FindVirtualMethod("i", void_sig, sizeof(void*));
+ ArtMethod* Jj1 = J->FindVirtualMethod("j1", void_sig, sizeof(void*));
+ ArtMethod* Jj2 = J->FindVirtualMethod("j2", void_sig, sizeof(void*));
+ ArtMethod* Kj1 = K->FindInterfaceMethod("j1", void_sig, sizeof(void*));
+ ArtMethod* Kj2 = K->FindInterfaceMethod("j2", void_sig, sizeof(void*));
+ ArtMethod* Kk = K->FindInterfaceMethod("k", void_sig, sizeof(void*));
+ ArtMethod* Ai = A->FindVirtualMethod("i", void_sig, sizeof(void*));
+ ArtMethod* Aj1 = A->FindVirtualMethod("j1", void_sig, sizeof(void*));
+ ArtMethod* Aj2 = A->FindVirtualMethod("j2", void_sig, sizeof(void*));
ASSERT_TRUE(Ii != nullptr);
ASSERT_TRUE(Jj1 != nullptr);
ASSERT_TRUE(Jj2 != nullptr);
@@ -1009,21 +994,17 @@
EXPECT_NE(Jj2, Aj2);
EXPECT_EQ(Kj1, Jj1);
EXPECT_EQ(Kj2, Jj2);
- EXPECT_EQ(Ai, A->FindVirtualMethodForInterface(Ii));
- EXPECT_EQ(Aj1, A->FindVirtualMethodForInterface(Jj1));
- EXPECT_EQ(Aj2, A->FindVirtualMethodForInterface(Jj2));
- EXPECT_EQ(Ai, A->FindVirtualMethodForVirtualOrInterface(Ii));
- EXPECT_EQ(Aj1, A->FindVirtualMethodForVirtualOrInterface(Jj1));
- EXPECT_EQ(Aj2, A->FindVirtualMethodForVirtualOrInterface(Jj2));
+ EXPECT_EQ(Ai, A->FindVirtualMethodForInterface(Ii, sizeof(void*)));
+ EXPECT_EQ(Aj1, A->FindVirtualMethodForInterface(Jj1, sizeof(void*)));
+ EXPECT_EQ(Aj2, A->FindVirtualMethodForInterface(Jj2, sizeof(void*)));
+ EXPECT_EQ(Ai, A->FindVirtualMethodForVirtualOrInterface(Ii, sizeof(void*)));
+ EXPECT_EQ(Aj1, A->FindVirtualMethodForVirtualOrInterface(Jj1, sizeof(void*)));
+ EXPECT_EQ(Aj2, A->FindVirtualMethodForVirtualOrInterface(Jj2, sizeof(void*)));
- ArtField* Afoo = mirror::Class::FindStaticField(soa.Self(), A, "foo",
- "Ljava/lang/String;");
- ArtField* Bfoo = mirror::Class::FindStaticField(soa.Self(), B, "foo",
- "Ljava/lang/String;");
- ArtField* Jfoo = mirror::Class::FindStaticField(soa.Self(), J, "foo",
- "Ljava/lang/String;");
- ArtField* Kfoo = mirror::Class::FindStaticField(soa.Self(), K, "foo",
- "Ljava/lang/String;");
+ ArtField* Afoo = mirror::Class::FindStaticField(soa.Self(), A, "foo", "Ljava/lang/String;");
+ ArtField* Bfoo = mirror::Class::FindStaticField(soa.Self(), B, "foo", "Ljava/lang/String;");
+ ArtField* Jfoo = mirror::Class::FindStaticField(soa.Self(), J, "foo", "Ljava/lang/String;");
+ ArtField* Kfoo = mirror::Class::FindStaticField(soa.Self(), K, "foo", "Ljava/lang/String;");
ASSERT_TRUE(Afoo != nullptr);
EXPECT_EQ(Afoo, Bfoo);
EXPECT_EQ(Afoo, Jfoo);
@@ -1043,17 +1024,17 @@
Handle<mirror::ClassLoader> class_loader(
hs.NewHandle(soa.Decode<mirror::ClassLoader*>(jclass_loader)));
mirror::Class* klass = class_linker_->FindClass(soa.Self(), "LStaticsFromCode;", class_loader);
- mirror::ArtMethod* clinit = klass->FindClassInitializer();
- mirror::ArtMethod* getS0 = klass->FindDirectMethod("getS0", "()Ljava/lang/Object;");
+ ArtMethod* clinit = klass->FindClassInitializer(sizeof(void*));
+ ArtMethod* getS0 = klass->FindDirectMethod("getS0", "()Ljava/lang/Object;", sizeof(void*));
const DexFile::StringId* string_id = dex_file->FindStringId("LStaticsFromCode;");
ASSERT_TRUE(string_id != nullptr);
const DexFile::TypeId* type_id = dex_file->FindTypeId(dex_file->GetIndexForStringId(*string_id));
ASSERT_TRUE(type_id != nullptr);
uint32_t type_idx = dex_file->GetIndexForTypeId(*type_id);
- mirror::Class* uninit = ResolveVerifyAndClinit(type_idx, clinit, Thread::Current(), true, false);
+ mirror::Class* uninit = ResolveVerifyAndClinit(type_idx, clinit, soa.Self(), true, false);
EXPECT_TRUE(uninit != nullptr);
EXPECT_FALSE(uninit->IsInitialized());
- mirror::Class* init = ResolveVerifyAndClinit(type_idx, getS0, Thread::Current(), true, false);
+ mirror::Class* init = ResolveVerifyAndClinit(type_idx, getS0, soa.Self(), true, false);
EXPECT_TRUE(init != nullptr);
EXPECT_TRUE(init->IsInitialized());
}
@@ -1109,22 +1090,23 @@
mirror::Class* c;
c = class_linker_->FindClass(soa.Self(), "Ljava/lang/Class;", class_loader);
- EXPECT_EQ(c->GetClassSize(), mirror::Class::ClassClassSize());
+ ASSERT_TRUE(c != nullptr);
+ EXPECT_EQ(c->GetClassSize(), mirror::Class::ClassClassSize(sizeof(void*)));
c = class_linker_->FindClass(soa.Self(), "Ljava/lang/Object;", class_loader);
- EXPECT_EQ(c->GetClassSize(), mirror::Object::ClassSize());
+ ASSERT_TRUE(c != nullptr);
+ EXPECT_EQ(c->GetClassSize(), mirror::Object::ClassSize(sizeof(void*)));
c = class_linker_->FindClass(soa.Self(), "Ljava/lang/String;", class_loader);
- EXPECT_EQ(c->GetClassSize(), mirror::String::ClassSize());
+ ASSERT_TRUE(c != nullptr);
+ EXPECT_EQ(c->GetClassSize(), mirror::String::ClassSize(sizeof(void*)));
c = class_linker_->FindClass(soa.Self(), "Ljava/lang/DexCache;", class_loader);
- EXPECT_EQ(c->GetClassSize(), mirror::DexCache::ClassSize());
-
- c = class_linker_->FindClass(soa.Self(), "Ljava/lang/reflect/ArtMethod;", class_loader);
- EXPECT_EQ(c->GetClassSize(), mirror::ArtMethod::ClassSize());
+ ASSERT_TRUE(c != nullptr);
+ EXPECT_EQ(c->GetClassSize(), mirror::DexCache::ClassSize(sizeof(void*)));
}
-static void CheckMethod(mirror::ArtMethod* method, bool verified)
+static void CheckMethod(ArtMethod* method, bool verified)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
if (!method->IsNative() && !method->IsAbstract()) {
EXPECT_EQ((method->GetAccessFlags() & kAccPreverified) != 0U, verified)
@@ -1136,11 +1118,11 @@
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
EXPECT_EQ((c->GetAccessFlags() & kAccPreverified) != 0U, preverified)
<< "Class " << PrettyClass(c) << " not as expected";
- for (uint32_t i = 0; i < c->NumDirectMethods(); ++i) {
- CheckMethod(c->GetDirectMethod(i), preverified);
+ for (auto& m : c->GetDirectMethods(sizeof(void*))) {
+ CheckMethod(&m, preverified);
}
- for (uint32_t i = 0; i < c->NumVirtualMethods(); ++i) {
- CheckMethod(c->GetVirtualMethod(i), preverified);
+ for (auto& m : c->GetVirtualMethods(sizeof(void*))) {
+ CheckMethod(&m, preverified);
}
}