ClassLinker can now FindClass all libcore classes
Summary:
- added ClassLinkerTest/LibCore test of finding all libcore classes
- fixed bug in LinkInterfaceMethods appending mirant methods to vtable_
- fixed bug in LinkVirtualMethods allocating subclass vtable_
- fixed mmap bug in MarkStack::Init
- bumped default (and max) heap sizes to handle ClassLinkerTest/LibCore
- made ObjectArray a templated class
- heap allocate Class::vtable_
- "mm test-art" and "mm test-art-target" added
- new is_host_ for use by tests
Details:
Added support for "mm test-art" and "mm test-art-target" in addition to test-art-host
Android.mk
Made ObjectArray a template class for clearer declarations and to
remove need the need for down_cast.
src/object.h
src/object_test.cc
src/class_linker.cc
src/class_linker.h
src/dex_cache.cc
src/dex_cache.h
src/dex_cache_test.cc
src/mark_sweep.cc
Made Class::vtable_ a heap allocated ObjectArray<Method>
src/class_linker.cc
Fix bug in ClassLinker::LinkInterfaceMethods where we were not
extending the vtable_ before appending miranda methods.
src/class_linker.cc
Changed all uses of DexFile* in ClassLinker to be const
src/class_linker.cc
src/class_linker.h
Fix bug in ClassLinker::LinkVirtualMethods where we were using
NumVirtualMethods vs vtable->GetLength when determining new max
vtable_ length.
src/class_linker.cc
New ClassLinkerTest/LibCore that enumerates the libcore dex file
and tries to FindClass every descriptor found.
src/class_linker_test.cc
Added if_host_ check for host only tests. In the future will use
for picking proper location of files, etc. on host vs target.
src/common_test.h
Fixed test to use ClassLinker::AllocDexCache
src/dex_cache_test.cc
Fixed fooIds comments to foo_ids_
src/dex_file.h
Bumped default heap size (and max as well) to make ClassLinkerTest/LibCore run
src/heap.h
Fixed bug where we were not using MAP_ANONYMOUS for MarkStack
allocation found running ClassLinkerTest/LibCore.
src/mark_stack.cc
Change-Id: I204e2ec7205210e2b60f5b81d126ab6e1da5a71c
diff --git a/Android.mk b/Android.mk
index f871c51..0c8b579 100644
--- a/Android.mk
+++ b/Android.mk
@@ -40,11 +40,27 @@
$(foreach file,$(TEST_HOST_SRC_FILES),$(HOST_OUT_EXECUTABLES)/$(notdir $(basename $(file:%.arm=%)))) \
#
+# "mm test-art" to build and run all tests on host and device
+.PHONY: test-art
+test-art: test-art-host test-art-target
+
# "mm test-art-host" to build and run all host tests
.PHONY: test-art-host
test-art-host: $(foreach file,$(TEST_HOST_SRC_FILES),$(HOST_OUT_EXECUTABLES)/$(notdir $(basename $(file:%.arm=%))))
$(foreach file,$(TEST_HOST_SRC_FILES),$(HOST_OUT_EXECUTABLES)/$(notdir $(basename $(file:%.arm=%))) &&) true
+# "mm test-art-device" to build and run all target tests
+.PHONY: test-art-target
+test-art-target: $(foreach file,$(TEST_TARGET_SRC_FILES),$(TARGET_OUT_EXECUTABLES)/$(notdir $(basename $(file:%.arm=%))))
+ adb remount
+ adb sync
+ adb shell touch /sdcard/test-art-target
+ adb shell rm /sdcard/test-art-target
+ adb shell sh -c "$(foreach file,$(TEST_TARGET_SRC_FILES), /system/bin/$(notdir $(basename $(file:%.arm=%))) &&) touch /sdcard/test-art-target"
+ adb pull /sdcard/test-art-target /tmp/
+ rm /tmp/test-art-target
+
+
# "mm cpplint-art" to style check art source files
.PHONY: cpplint-art
cpplint-art:
diff --git a/src/class_linker.cc b/src/class_linker.cc
index 78b6d33..22bcca6 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -86,7 +86,7 @@
CHECK(java_io_Serializable_ != NULL);
java_io_Serializable_->descriptor_ = "Ljava/io/Serializable;";
- array_interfaces_ = AllocObjectArray(2);
+ array_interfaces_ = AllocObjectArray<Class>(2);
CHECK(array_interfaces_ != NULL);
array_interfaces_->Set(0, java_lang_Cloneable_);
array_interfaces_->Set(1, java_io_Serializable_);
@@ -98,8 +98,8 @@
array_iftable_ = new InterfaceEntry[2];
CHECK(array_iftable_ != NULL);
memset(array_iftable_, 0, sizeof(InterfaceEntry) * 2);
- array_iftable_[0].SetClass(down_cast<Class*>(array_interfaces_->Get(0)));
- array_iftable_[1].SetClass(down_cast<Class*>(array_interfaces_->Get(1)));
+ array_iftable_[0].SetClass(array_interfaces_->Get(0));
+ array_iftable_[1].SetClass(array_interfaces_->Get(1));
char_array_class_ = FindSystemClass("[C");
CHECK(char_array_class_ != NULL);
@@ -113,7 +113,7 @@
}
DexCache* ClassLinker::AllocDexCache() {
- return down_cast<DexCache*>(Heap::AllocObjectArray(object_array_class_, DexCache::kMax));
+ return down_cast<DexCache*>(Heap::AllocObjectArray<Object>(object_array_class_, DexCache::kMax));
}
Class* ClassLinker::AllocClass(DexCache* dex_cache) {
@@ -137,10 +137,6 @@
sizeof(Method)));
}
-ObjectArray* ClassLinker::AllocObjectArray(size_t length) {
- return Heap::AllocObjectArray(object_array_class_, length);
-}
-
Class* ClassLinker::FindClass(const StringPiece& descriptor,
Object* class_loader,
const DexFile* dex_file) {
@@ -290,7 +286,7 @@
// Load static fields.
DCHECK(klass->sfields_ == NULL);
if (num_static_fields != 0) {
- klass->sfields_ = AllocObjectArray(num_static_fields);
+ klass->sfields_ = AllocObjectArray<StaticField>(num_static_fields);
uint32_t last_idx = 0;
for (size_t i = 0; i < klass->NumStaticFields(); ++i) {
DexFile::Field dex_field;
@@ -305,7 +301,7 @@
DCHECK(klass->ifields_ == NULL);
if (num_instance_fields != 0) {
// TODO: allocate on the object heap.
- klass->ifields_ = AllocObjectArray(num_instance_fields);
+ klass->ifields_ = AllocObjectArray<InstanceField>(num_instance_fields);
uint32_t last_idx = 0;
for (size_t i = 0; i < klass->NumInstanceFields(); ++i) {
DexFile::Field dex_field;
@@ -320,7 +316,7 @@
DCHECK(klass->direct_methods_ == NULL);
if (num_direct_methods != 0) {
// TODO: append direct methods to class object
- klass->direct_methods_ = AllocObjectArray(num_direct_methods);
+ klass->direct_methods_ = AllocObjectArray<Method>(num_direct_methods);
uint32_t last_idx = 0;
for (size_t i = 0; i < klass->NumDirectMethods(); ++i) {
DexFile::Method dex_method;
@@ -336,7 +332,7 @@
DCHECK(klass->virtual_methods_ == NULL);
if (num_virtual_methods != 0) {
// TODO: append virtual methods to class object
- klass->virtual_methods_ = AllocObjectArray(num_virtual_methods);
+ klass->virtual_methods_ = AllocObjectArray<Method>(num_virtual_methods);
uint32_t last_idx = 0;
for (size_t i = 0; i < klass->NumVirtualMethods(); ++i) {
DexFile::Method dex_method;
@@ -355,7 +351,7 @@
const DexFile::TypeList* list = dex_file.GetInterfacesList(dex_class_def);
if (list != NULL) {
DCHECK(klass->interfaces_ == NULL);
- klass->interfaces_ = AllocObjectArray(list->Size());
+ klass->interfaces_ = AllocObjectArray<Class>(list->Size());
DCHECK(klass->interfaces_idx_ == NULL);
klass->interfaces_idx_ = new uint32_t[list->Size()];
for (size_t i = 0; i < list->Size(); ++i) {
@@ -407,7 +403,7 @@
ClassLinker::ClassPathEntry ClassLinker::FindInBootClassPath(const StringPiece& descriptor) {
for (size_t i = 0; i != boot_class_path_.size(); ++i) {
- DexFile* dex_file = boot_class_path_[i];
+ const DexFile* dex_file = boot_class_path_[i];
const DexFile::ClassDef* dex_class_def = dex_file->FindClassDef(descriptor);
if (dex_class_def != NULL) {
return ClassPathEntry(dex_file, dex_class_def);
@@ -422,15 +418,15 @@
RegisterDexFile(dex_file);
}
-void ClassLinker::RegisterDexFile(DexFile* dex_file) {
+void ClassLinker::RegisterDexFile(const DexFile* dex_file) {
CHECK(dex_file != NULL);
dex_files_.push_back(dex_file);
DexCache* dex_cache = AllocDexCache();
CHECK(dex_cache != NULL);
- dex_cache->Init(AllocObjectArray(dex_file->NumStringIds()),
- AllocObjectArray(dex_file->NumTypeIds()),
- AllocObjectArray(dex_file->NumMethodIds()),
- AllocObjectArray(dex_file->NumFieldIds()));
+ dex_cache->Init(AllocObjectArray<String>(dex_file->NumStringIds()),
+ AllocObjectArray<Class>(dex_file->NumTypeIds()),
+ AllocObjectArray<Method>(dex_file->NumMethodIds()),
+ AllocObjectArray<Field>(dex_file->NumFieldIds()));
dex_caches_.push_back(dex_cache);
}
@@ -569,7 +565,6 @@
new_class->descriptor_.set(new_class->descriptor_alloc_->data(),
new_class->descriptor_alloc_->size());
new_class->super_class_ = java_lang_Object_;
- new_class->vtable_count_ = java_lang_Object_->vtable_count_;
new_class->vtable_ = java_lang_Object_->vtable_;
new_class->primitive_type_ = Class::kPrimNot;
new_class->component_type_ = component_type_;
@@ -1113,38 +1108,36 @@
bool ClassLinker::LinkVirtualMethods(Class* klass) {
uint32_t max_count = klass->NumVirtualMethods();
if (klass->GetSuperClass() != NULL) {
- max_count += klass->GetSuperClass()->NumVirtualMethods();
+ max_count += klass->GetSuperClass()->vtable_->GetLength();
} else {
CHECK(klass->GetDescriptor() == "Ljava/lang/Object;");
}
// TODO: do not assign to the vtable field until it is fully constructed.
- // TODO: make this a vector<Method*> instead?
- klass->vtable_ = new Method*[max_count];
+ klass->vtable_ = AllocObjectArray<Method>(max_count);
if (klass->HasSuperClass()) {
- memcpy(klass->vtable_,
- klass->GetSuperClass()->vtable_,
- klass->GetSuperClass()->vtable_count_ * sizeof(Method*));
- size_t actual_count = klass->GetSuperClass()->vtable_count_;
+ size_t actual_count = klass->GetSuperClass()->vtable_->GetLength();
+ CHECK_LE(actual_count, max_count);
+ ObjectArray<Method>::Copy(klass->GetSuperClass()->vtable_, 0, klass->vtable_, 0, actual_count);
// See if any of our virtual methods override the superclass.
for (size_t i = 0; i < klass->NumVirtualMethods(); ++i) {
Method* local_method = klass->GetVirtualMethod(i);
size_t j = 0;
- for (; j < klass->GetSuperClass()->vtable_count_; ++j) {
- const Method* super_method = klass->vtable_[j];
+ for (; j < actual_count; ++j) {
+ Method* super_method = klass->vtable_->Get(j);
if (HasSameNameAndPrototype(local_method, super_method)) {
// Verify
if (super_method->IsFinal()) {
LG << "Method overrides final method"; // TODO: VirtualMachineError
return false;
}
- klass->vtable_[j] = local_method;
+ klass->vtable_->Set(j, local_method);
local_method->method_index_ = j;
break;
}
}
- if (j == klass->GetSuperClass()->vtable_count_) {
+ if (j == actual_count) {
// Not overriding, append.
- klass->vtable_[actual_count] = local_method;
+ klass->vtable_->Set(actual_count, local_method);
local_method->method_index_ = actual_count;
actual_count += 1;
}
@@ -1155,15 +1148,13 @@
}
CHECK_LE(actual_count, max_count);
if (actual_count < max_count) {
- Method** new_vtable = new Method*[actual_count];
- memcpy(new_vtable, klass->vtable_, actual_count * sizeof(Method*));
- delete[] klass->vtable_;
+ ObjectArray<Method>* new_vtable = AllocObjectArray<Method>(actual_count);
+ ObjectArray<Method>::Copy(klass->vtable_, 0, new_vtable, 0, actual_count);
klass->vtable_ = new_vtable;
LG << "shrunk vtable: "
<< "was " << max_count << ", "
<< "now " << actual_count;
}
- klass->vtable_count_ = actual_count;
} else {
CHECK(klass->GetDescriptor() == "Ljava/lang/Object;");
if (!IsUint(16, klass->NumVirtualMethods())) {
@@ -1171,10 +1162,9 @@
return false;
}
for (size_t i = 0; i < klass->NumVirtualMethods(); ++i) {
- klass->vtable_[i] = klass->GetVirtualMethod(i);
+ klass->vtable_->Set(i, klass->GetVirtualMethod(i));
klass->GetVirtualMethod(i)->method_index_ = i & 0xFFFF;
}
- klass->vtable_count_ = klass->NumVirtualMethods();
}
return true;
}
@@ -1241,9 +1231,9 @@
for (size_t j = 0; j < interface->NumVirtualMethods(); ++j) {
Method* interface_method = interface->GetVirtualMethod(j);
int k; // must be signed
- for (k = klass->vtable_count_ - 1; k >= 0; --k) {
- if (HasSameNameAndPrototype(interface_method, klass->vtable_[k])) {
- if (!klass->vtable_[k]->IsPublic()) {
+ for (k = klass->vtable_->GetLength() - 1; k >= 0; --k) {
+ if (HasSameNameAndPrototype(interface_method, klass->vtable_->Get(k))) {
+ if (!klass->vtable_->Get(k)->IsPublic()) {
LG << "Implementation not public";
return false;
}
@@ -1267,7 +1257,7 @@
}
}
// point the interface table at a phantom slot index
- klass->iftable_[i].method_index_array_[j] = klass->vtable_count_ + mir;
+ klass->iftable_[i].method_index_array_[j] = klass->vtable_->GetLength() + mir;
if (mir == miranda_count) {
miranda_list[miranda_count++] = interface_method;
}
@@ -1277,17 +1267,20 @@
if (miranda_count != 0) {
int old_method_count = klass->NumVirtualMethods();
int new_method_count = old_method_count + miranda_count;
- ObjectArray* new_virtual_methods = AllocObjectArray(new_method_count);
- if (klass->virtual_methods_ != NULL) {
- ObjectArray::Copy(klass->virtual_methods_, 0,
- new_virtual_methods, 0,
- old_method_count);
- }
+ ObjectArray<Method>* new_virtual_methods = AllocObjectArray<Method>(new_method_count);
+ ObjectArray<Method>::Copy(klass->virtual_methods_, 0,
+ new_virtual_methods, 0,
+ old_method_count);
klass->virtual_methods_ = new_virtual_methods;
CHECK(klass->vtable_ != NULL);
- int old_vtable_count = klass->vtable_count_;
- klass->vtable_count_ += miranda_count;
+ int old_vtable_count = klass->vtable_->GetLength();
+ int new_vtable_count = old_vtable_count + miranda_count;
+ ObjectArray<Method>* new_vtable = AllocObjectArray<Method>(new_vtable_count);
+ ObjectArray<Method>::Copy(klass->vtable_, 0,
+ new_vtable, 0,
+ old_vtable_count);
+ klass->vtable_ = new_vtable;
for (int i = 0; i < miranda_count; i++) {
Method* meth = AllocMethod();
@@ -1296,7 +1289,7 @@
meth->access_flags_ |= kAccMiranda;
meth->method_index_ = 0xFFFF & (old_vtable_count + i);
klass->SetVirtualMethod(old_method_count + i, meth);
- klass->vtable_[old_vtable_count + i] = meth;
+ klass->vtable_->Set(old_vtable_count + i, meth);
}
}
return true;
diff --git a/src/class_linker.h b/src/class_linker.h
index a2f2770..086234d 100644
--- a/src/class_linker.h
+++ b/src/class_linker.h
@@ -7,6 +7,7 @@
#include <utility>
#include <vector>
+#include "heap.h"
#include "macros.h"
#include "dex_file.h"
#include "thread.h"
@@ -27,7 +28,10 @@
StaticField* AllocStaticField();
InstanceField* AllocInstanceField();
Method* AllocMethod();
- ObjectArray* AllocObjectArray(size_t length);
+ template <class C> ObjectArray<C>* AllocObjectArray(size_t length) {
+ return Heap::AllocObjectArray<C>(object_array_class_, length);
+ }
+
// Finds a class by its descriptor name.
// If dex_file is null, searches boot_class_path_.
@@ -49,7 +53,7 @@
String* ResolveString(const Class* referring, uint32_t string_idx);
- void RegisterDexFile(DexFile* dex_file);
+ void RegisterDexFile(const DexFile* dex_file);
private:
ClassLinker() {}
@@ -144,9 +148,9 @@
void CreateReferenceOffsets(Class* klass);
- std::vector<DexFile*> boot_class_path_;
+ std::vector<const DexFile*> boot_class_path_;
- std::vector<DexFile*> dex_files_;
+ std::vector<const DexFile*> dex_files_;
std::vector<DexCache*> dex_caches_;
@@ -183,7 +187,7 @@
Class* field_array_class_;
Class* method_array_class_;
- ObjectArray* array_interfaces_;
+ ObjectArray<Class>* array_interfaces_;
InterfaceEntry* array_iftable_;
FRIEND_TEST(ClassLinkerTest, ProtoCompare);
diff --git a/src/class_linker_test.cc b/src/class_linker_test.cc
index 41fa5b1..4f921c4 100644
--- a/src/class_linker_test.cc
+++ b/src/class_linker_test.cc
@@ -4,6 +4,7 @@
#include "class_linker.h"
#include "dex_file.h"
#include "heap.h"
+#include "stringprintf.h"
#include "gtest/gtest.h"
namespace art {
@@ -72,6 +73,23 @@
EXPECT_EQ(0U, array->NumStaticFields());
EXPECT_EQ(2U, array->NumInterfaces());
}
+
+ void AssertDexFileClass(const DexFile* dex, const char* descriptor) {
+ CHECK(descriptor != NULL);
+ Class* klass = class_linker_->FindClass(descriptor, NULL, dex);
+ CHECK(klass != NULL);
+ }
+
+ void AssertDexFile(const DexFile* dex) {
+ CHECK(dex != NULL);
+ class_linker_->RegisterDexFile(dex);
+ for (size_t i = 0; i < dex->NumClassDefs(); i++) {
+ const DexFile::ClassDef class_def = dex->GetClassDef(i);
+ const char* descriptor = dex->GetClassDescriptor(class_def);
+ AssertDexFileClass(dex, descriptor);
+ }
+ }
+
};
TEST_F(ClassLinkerTest, FindClassNonexistent) {
@@ -273,4 +291,17 @@
EXPECT_TRUE(linker->HasSameNameAndPrototype(m4_2, m4_1));
}
+TEST_F(ClassLinkerTest, LibCore) {
+ // TODO add host support when we have DexFile::OpenJar
+ if (!is_host_) {
+ return;
+ }
+
+ // TODO switch to jar when we have DexFile::OpenJar
+ std::string libcore_dex_file_name = StringPrintf("%s/out/target/common/obj/JAVA_LIBRARIES/core_intermediates/noproguard.classes.dex",
+ getenv("ANDROID_BUILD_TOP"));
+ scoped_ptr<DexFile> libcore_dex_file(DexFile::OpenFile(libcore_dex_file_name.c_str()));
+ AssertDexFile(libcore_dex_file.get());
+}
+
} // namespace art
diff --git a/src/common_test.h b/src/common_test.h
index 237939b..1c4790b 100644
--- a/src/common_test.h
+++ b/src/common_test.h
@@ -173,6 +173,8 @@
class RuntimeTest : public testing::Test {
protected:
virtual void SetUp() {
+ is_host_ = getenv("ANDROID_BUILD_TOP") != NULL;
+
java_lang_dex_file_.reset(OpenDexFileBase64(kJavaLangDex));
std::vector<DexFile*> boot_class_path;
@@ -183,6 +185,7 @@
class_linker_ = runtime_->GetClassLinker();
}
+ bool is_host_;
scoped_ptr<DexFile> java_lang_dex_file_;
scoped_ptr<Runtime> runtime_;
ClassLinker* class_linker_;
diff --git a/src/dex_cache.cc b/src/dex_cache.cc
index f2a4768..8ab4130 100644
--- a/src/dex_cache.cc
+++ b/src/dex_cache.cc
@@ -8,10 +8,10 @@
namespace art {
-void DexCache::Init(ObjectArray* strings,
- ObjectArray* classes,
- ObjectArray* methods,
- ObjectArray* fields) {
+void DexCache::Init(ObjectArray<String>* strings,
+ ObjectArray<Class>* classes,
+ ObjectArray<Method>* methods,
+ ObjectArray<Field>* fields) {
Set(kStrings, strings);
Set(kClasses, classes);
Set(kMethods, methods);
diff --git a/src/dex_cache.h b/src/dex_cache.h
index 2892e29..47f9bcf 100644
--- a/src/dex_cache.h
+++ b/src/dex_cache.h
@@ -15,7 +15,7 @@
class String;
union JValue;
-class DexCache : public ObjectArray {
+class DexCache : public ObjectArray<Object> {
public:
enum ArrayIndexes {
@@ -26,10 +26,10 @@
kMax = 4,
};
- void Init(ObjectArray* strings,
- ObjectArray* classes,
- ObjectArray* methods,
- ObjectArray* fields);
+ void Init(ObjectArray<String>* strings,
+ ObjectArray<Class>* classes,
+ ObjectArray<Method>* methods,
+ ObjectArray<Field>* fields);
size_t NumStrings() const {
return GetStrings()->GetLength();
@@ -48,7 +48,7 @@
}
String* GetResolvedString(uint32_t string_idx) const {
- return down_cast<String*>(GetStrings()->Get(string_idx));
+ return GetStrings()->Get(string_idx);
}
void SetResolvedString(uint32_t string_idx, String* resolved) {
@@ -56,7 +56,7 @@
}
Class* GetResolvedClass(uint32_t class_idx) const {
- return down_cast<Class*>(GetClasses()->Get(class_idx));
+ return GetClasses()->Get(class_idx);
}
void SetResolvedClass(uint32_t class_idx, Class* resolved) {
@@ -64,7 +64,7 @@
}
Method* GetResolvedMethod(uint32_t method_idx) const {
- return down_cast<Method*>(GetMethods()->Get(method_idx));
+ return GetMethods()->Get(method_idx);
}
void SetResolvedMethod(uint32_t method_idx, Method* resolved) {
@@ -72,7 +72,7 @@
}
Field* GetResolvedField(uint32_t field_idx) const {
- return down_cast<Field*>(GetFields()->Get(field_idx));
+ return GetFields()->Get(field_idx);
}
void SetResolvedfield(uint32_t field_idx, Field* resolved) {
@@ -80,17 +80,17 @@
}
private:
- ObjectArray* GetStrings() const {
- return down_cast<ObjectArray*>(Get(kStrings));
+ ObjectArray<String>* GetStrings() const {
+ return down_cast<ObjectArray<String>*>(Get(kStrings));
}
- ObjectArray* GetClasses() const {
- return down_cast<ObjectArray*>(Get(kClasses));
+ ObjectArray<Class>* GetClasses() const {
+ return down_cast<ObjectArray<Class>*>(Get(kClasses));
}
- ObjectArray* GetMethods() const {
- return down_cast<ObjectArray*>(Get(kMethods));
+ ObjectArray<Method>* GetMethods() const {
+ return down_cast<ObjectArray<Method>*>(Get(kMethods));
}
- ObjectArray* GetFields() const {
- return down_cast<ObjectArray*>(Get(kFields));
+ ObjectArray<Field>* GetFields() const {
+ return down_cast<ObjectArray<Field>*>(Get(kFields));
}
DexCache();
};
diff --git a/src/dex_cache_test.cc b/src/dex_cache_test.cc
index 7cfb634..c439311 100644
--- a/src/dex_cache_test.cc
+++ b/src/dex_cache_test.cc
@@ -16,12 +16,12 @@
TEST_F(DexCacheTest, Open) {
- DexCache* dex_cache = down_cast<DexCache*>(class_linker_->AllocObjectArray(DexCache::kMax));
+ DexCache* dex_cache = class_linker_->AllocDexCache();
ASSERT_TRUE(dex_cache != NULL);
- dex_cache->Init(class_linker_->AllocObjectArray(1),
- class_linker_->AllocObjectArray(2),
- class_linker_->AllocObjectArray(3),
- class_linker_->AllocObjectArray(4));
+ dex_cache->Init(class_linker_->AllocObjectArray<String>(1),
+ class_linker_->AllocObjectArray<Class>(2),
+ class_linker_->AllocObjectArray<Method>(3),
+ class_linker_->AllocObjectArray<Field>(4));
EXPECT_EQ(1U, dex_cache->NumStrings());
EXPECT_EQ(2U, dex_cache->NumClasses());
EXPECT_EQ(3U, dex_cache->NumMethods());
diff --git a/src/dex_file.h b/src/dex_file.h
index 4d00537..63fefae 100644
--- a/src/dex_file.h
+++ b/src/dex_file.h
@@ -87,16 +87,16 @@
// Raw field_id_item.
struct FieldId {
- uint16_t class_idx_; // index into typeIds list for defining class
- uint16_t type_idx_; // index into typeIds for field type
- uint32_t name_idx_; // index into stringIds for field name
+ uint16_t class_idx_; // index into type_ids_ list for defining class
+ uint16_t type_idx_; // index into type_ids_ for field type
+ uint32_t name_idx_; // index into string_ids_ for field name
};
// Raw method_id_item.
struct MethodId {
- uint16_t class_idx_; // index into typeIds list for defining class
- uint16_t proto_idx_; // index into protoIds for method prototype
- uint32_t name_idx_; // index into stringIds for method name
+ uint16_t class_idx_; // index into type_ids_ list for defining class
+ uint16_t proto_idx_; // index into proto_ids_ for method prototype
+ uint32_t name_idx_; // index into string_ids_ for method name
};
// Raw proto_id_item.
@@ -108,11 +108,11 @@
// Raw class_def_item.
struct ClassDef {
- uint32_t class_idx_; // index into typeIds for this class
+ uint32_t class_idx_; // index into type_ids_ for this class
uint32_t access_flags_;
- uint32_t superclass_idx_; // index into typeIds for superclass
+ uint32_t superclass_idx_; // index into type_ids_ for superclass
uint32_t interfaces_off_; // file offset to TypeList
- uint32_t source_file_idx_; // index into stringIds for source file name
+ uint32_t source_file_idx_; // index into string_ids_ for source file name
uint32_t annotations_off_; // file offset to annotations_directory_item
uint32_t class_data_off_; // file offset to class_data_item
uint32_t static_values_off_; // file offset to EncodedArray
diff --git a/src/heap.h b/src/heap.h
index 4aff139..e54135e 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -18,9 +18,9 @@
class Heap {
public:
- static const size_t kStartupSize = 1 * MB;
+ static const size_t kStartupSize = 16 * MB;
- static const size_t kMaximumSize = 16 * MB;
+ static const size_t kMaximumSize = 64 * MB;
static bool Init() {
return Init(kStartupSize, kMaximumSize);
@@ -46,11 +46,11 @@
return array;
}
- static ObjectArray* AllocObjectArray(Class* object_array_class,
- size_t length) {
- return down_cast<ObjectArray*>(AllocArray(object_array_class,
- length,
- sizeof(uint32_t)));
+ template <class C> static ObjectArray<C>* AllocObjectArray(Class* object_array_class,
+ size_t length) {
+ return down_cast<ObjectArray<C>*>(AllocArray(object_array_class,
+ length,
+ sizeof(uint32_t)));
}
static CharArray* AllocCharArray(Class* char_array_class, size_t length) {
diff --git a/src/mark_stack.cc b/src/mark_stack.cc
index c6d7712..5dc4f77 100644
--- a/src/mark_stack.cc
+++ b/src/mark_stack.cc
@@ -23,7 +23,7 @@
bool MarkStack::Init(size_t maximum_size) {
size_t length = 64 * MB;
- void* addr = mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_PRIVATE, -1, 0);
+ void* addr = mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (addr == MAP_FAILED) {
PLOG(ERROR) << "mmap failed";
return false;
diff --git a/src/mark_sweep.cc b/src/mark_sweep.cc
index 196c83c..2cfb0c6 100644
--- a/src/mark_sweep.cc
+++ b/src/mark_sweep.cc
@@ -206,7 +206,7 @@
DCHECK(obj->GetClass() != NULL);
MarkObject(obj->GetClass());
if (obj->IsObjectArray()) {
- const ObjectArray* array = obj->AsObjectArray();
+ const ObjectArray<Object>* array = obj->AsObjectArray();
for (size_t i = 0; i < array->GetLength(); ++i) {
const Object* element = array->Get(i);
MarkObject(element);
diff --git a/src/object.h b/src/object.h
index d0b2f13..bf965df 100644
--- a/src/object.h
+++ b/src/object.h
@@ -22,7 +22,7 @@
class Monitor;
class Method;
class Object;
-class ObjectArray;
+template<class T> class ObjectArray;
class StaticField;
union JValue {
@@ -169,8 +169,8 @@
return true;
}
- const ObjectArray* AsObjectArray() const {
- return down_cast<const ObjectArray*>(this);
+ const ObjectArray<Object>* AsObjectArray() const {
+ return down_cast<const ObjectArray<Object>*>(this);
}
bool IsReference() const {
@@ -584,19 +584,20 @@
Array();
};
+template<class T>
class ObjectArray : public Array {
public:
- Object* Get(uint32_t i) const {
+ C* Get(uint32_t i) const {
DCHECK_LT(i, GetLength());
Object* const * data = reinterpret_cast<Object* const *>(GetData());
- return data[i];
+ return down_cast<C*>(data[i]);
}
- void Set(uint32_t i, Object* object) {
+ void Set(uint32_t i, C* object) {
DCHECK_LT(i, GetLength());
- Object** data = reinterpret_cast<Object**>(GetData());
+ C** data = reinterpret_cast<C**>(GetData());
data[i] = object;
}
- static void Copy(ObjectArray* src, int src_pos, ObjectArray* dst, int dst_pos, size_t length) {
+ static void Copy(ObjectArray<C>* src, int src_pos, ObjectArray<C>* dst, int dst_pos, size_t length) {
for (size_t i = 0; i < length; i++) {
dst->Set(dst_pos + i, src->Get(src_pos + i));
}
@@ -741,7 +742,7 @@
}
Method* GetDirectMethod(uint32_t i) const {
- return down_cast<Method*>(direct_methods_->Get(i));
+ return direct_methods_->Get(i);
}
void SetDirectMethod(uint32_t i, Method* f) { // TODO: uint16_t
@@ -754,7 +755,7 @@
}
Method* GetVirtualMethod(uint32_t i) const {
- return down_cast<Method*>(virtual_methods_->Get(i));
+ return virtual_methods_->Get(i);
}
void SetVirtualMethod(uint32_t i, Method* f) { // TODO: uint16_t
@@ -771,7 +772,7 @@
}
InstanceField* GetInstanceField(uint32_t i) { // TODO: uint16_t
- return down_cast<InstanceField*>(ifields_->Get(i));
+ return ifields_->Get(i);
}
void SetInstanceField(uint32_t i, InstanceField* f) { // TODO: uint16_t
@@ -783,7 +784,7 @@
}
StaticField* GetStaticField(uint32_t i) const { // TODO: uint16_t
- return down_cast<StaticField*>(sfields_->Get(i));
+ return sfields_->Get(i);
}
void SetStaticField(uint32_t i, StaticField* f) { // TODO: uint16_t
@@ -807,7 +808,7 @@
}
Class* GetInterface(uint32_t i) const {
- return down_cast<Class*>(interfaces_->Get(i));
+ return interfaces_->Get(i);
}
void SetInterface(uint32_t i, Class* f) { // TODO: uint16_t
@@ -879,20 +880,19 @@
// InitiatingLoaderList initiating_loader_list_;
// array of interfaces this class implements directly
- ObjectArray* interfaces_;
+ ObjectArray<Class>* interfaces_;
uint32_t* interfaces_idx_;
// static, private, and <init> methods
- ObjectArray* direct_methods_;
+ ObjectArray<Method>* direct_methods_;
// virtual methods defined in this class; invoked through vtable
- ObjectArray* virtual_methods_;
+ ObjectArray<Method>* virtual_methods_;
// Virtual method table (vtable), for use by "invoke-virtual". The
// vtable from the superclass is copied in, and virtual methods from
// our class either replace those from the super or are appended.
- size_t vtable_count_;
- Method** vtable_;
+ ObjectArray<Method>* vtable_;
// Interface table (iftable), one entry per interface supported by
// this class. That means one entry for each interface we support
@@ -926,7 +926,7 @@
// All instance fields that refer to objects are guaranteed to be at
// the beginning of the field list. num_reference_instance_fields_
// specifies the number of reference fields.
- ObjectArray* ifields_;
+ ObjectArray<InstanceField>* ifields_;
// number of fields that are object refs
size_t num_reference_instance_fields_;
@@ -938,7 +938,7 @@
const char* source_file_;
// Static fields
- ObjectArray* sfields_;
+ ObjectArray<StaticField>* sfields_;
private:
Class();
diff --git a/src/object_test.cc b/src/object_test.cc
index 6598167..dc74b8b 100644
--- a/src/object_test.cc
+++ b/src/object_test.cc
@@ -30,7 +30,7 @@
}
TEST_F(ObjectTest, AllocObjectArray) {
- ObjectArray* oa = class_linker_->AllocObjectArray(2);
+ ObjectArray<Object>* oa = class_linker_->AllocObjectArray<Object>(2);
EXPECT_EQ(2U, oa->GetLength());
EXPECT_TRUE(oa->Get(0) == NULL);
EXPECT_TRUE(oa->Get(1) == NULL);