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/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);