Add ObjectArray::CopyOf

As part of doing this, moved Heap::Alloc* helpers to the corresponding
classes in object.h to break heap.h<->object.h cycle due to use of
Heap from ObjectArray::CopyOf (which is templatized and needs to be
defined in .h file).

Change-Id: I1870af6e9dc6552820034ead5e20d13ae4da67da
diff --git a/src/class_linker.cc b/src/class_linker.cc
index 22bcca6..5db2bea 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -113,11 +113,11 @@
 }
 
 DexCache* ClassLinker::AllocDexCache() {
-  return down_cast<DexCache*>(Heap::AllocObjectArray<Object>(object_array_class_, DexCache::kMax));
+  return down_cast<DexCache*>(AllocObjectArray<Object>(DexCache::kMax));
 }
 
 Class* ClassLinker::AllocClass(DexCache* dex_cache) {
-  Class* klass = down_cast<Class*>(Heap::AllocObject(java_lang_Class_));
+  Class* klass = down_cast<Class*>(Object::Alloc(java_lang_Class_));
   klass->dex_cache_ = dex_cache;
   return klass;
 }
@@ -1106,18 +1106,12 @@
 }
 
 bool ClassLinker::LinkVirtualMethods(Class* klass) {
-  uint32_t max_count = klass->NumVirtualMethods();
-  if (klass->GetSuperClass() != NULL) {
-    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.
-  klass->vtable_ = AllocObjectArray<Method>(max_count);
   if (klass->HasSuperClass()) {
+    uint32_t max_count = klass->NumVirtualMethods() + klass->GetSuperClass()->vtable_->GetLength();
     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);
+    // TODO: do not assign to the vtable field until it is fully constructed.
+    klass->vtable_ = klass->GetSuperClass()->vtable_->CopyOf(max_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);
@@ -1148,20 +1142,23 @@
     }
     CHECK_LE(actual_count, max_count);
     if (actual_count < max_count) {
-      ObjectArray<Method>* new_vtable = AllocObjectArray<Method>(actual_count);
-      ObjectArray<Method>::Copy(klass->vtable_, 0, new_vtable, 0, actual_count);
-      klass->vtable_ = new_vtable;
+      // TODO: do not assign to the vtable field until it is fully constructed.
+      klass->vtable_ = klass->vtable_->CopyOf(actual_count);
       LG << "shrunk vtable: "
          << "was " << max_count << ", "
          << "now " << actual_count;
     }
   } else {
     CHECK(klass->GetDescriptor() == "Ljava/lang/Object;");
-    if (!IsUint(16, klass->NumVirtualMethods())) {
+    uint32_t num_virtual_methods = klass->NumVirtualMethods();
+    CHECK(klass->GetDescriptor() == "Ljava/lang/Object;");
+    if (!IsUint(16, num_virtual_methods)) {
       LG << "Too many methods";  // TODO: VirtualMachineError
       return false;
     }
-    for (size_t i = 0; i < klass->NumVirtualMethods(); ++i) {
+    // TODO: do not assign to the vtable field until it is fully constructed.
+    klass->vtable_ = AllocObjectArray<Method>(num_virtual_methods);
+    for (size_t i = 0; i < num_virtual_methods; ++i) {
       klass->vtable_->Set(i, klass->GetVirtualMethod(i));
       klass->GetVirtualMethod(i)->method_index_ = i & 0xFFFF;
     }
@@ -1267,20 +1264,13 @@
   if (miranda_count != 0) {
     int old_method_count = klass->NumVirtualMethods();
     int new_method_count = old_method_count + miranda_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;
+    klass->virtual_methods_ = klass->virtual_methods_->CopyOf(new_method_count);
 
     CHECK(klass->vtable_ != NULL);
     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;
+    // TODO: do not assign to the vtable field until it is fully constructed.
+    klass->vtable_ = klass->vtable_->CopyOf(new_vtable_count);
 
     for (int i = 0; i < miranda_count; i++) {
       Method* meth = AllocMethod();
@@ -1511,9 +1501,9 @@
   const DexFile* dex_file = FindDexFile(referring->GetDexCache());
   const DexFile::StringId& string_id = dex_file->GetStringId(string_idx);
   const char* string_data = dex_file->GetStringData(string_id);
-  String* new_string = Heap::AllocStringFromModifiedUtf8(java_lang_String_,
-                                                         char_array_class_,
-                                                         string_data);
+  String* new_string = String::AllocFromModifiedUtf8(java_lang_String_,
+                                                     char_array_class_,
+                                                     string_data);
   // TODO: intern the new string
   referring->GetDexCache()->SetResolvedString(string_idx, new_string);
   return new_string;
diff --git a/src/class_linker.h b/src/class_linker.h
index 086234d..738979b 100644
--- a/src/class_linker.h
+++ b/src/class_linker.h
@@ -28,8 +28,10 @@
   StaticField* AllocStaticField();
   InstanceField* AllocInstanceField();
   Method* AllocMethod();
-  template <class C> ObjectArray<C>* AllocObjectArray(size_t length) {
-    return Heap::AllocObjectArray<C>(object_array_class_, length);
+
+  template <class T>
+  ObjectArray<T>* AllocObjectArray(size_t length) {
+    return ObjectArray<T>::Alloc(object_array_class_, length);
   }
 
 
diff --git a/src/heap.cc b/src/heap.cc
index 851433b..6ec6aac 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -66,10 +66,6 @@
   delete live_bitmap_;
 }
 
-Object* Heap::AllocObject(Class* klass) {
-  return AllocObject(klass, klass->object_size_);
-}
-
 Object* Heap::AllocObject(Class* klass, size_t num_bytes) {
   Object* obj = Allocate(num_bytes);
   if (obj != NULL) {
@@ -179,17 +175,6 @@
   return NULL;
 }
 
-String* Heap::AllocStringFromModifiedUtf8(Class* java_lang_String,
-                                          Class* char_array,
-                                          const char* data) {
-  String* string = AllocString(java_lang_String);
-  uint32_t count = strlen(data);  // TODO
-  CharArray* array = AllocCharArray(char_array, count);
-  string->array_ = array;
-  string->count_ = count;
-  return string;
-}
-
 void Heap::CollectGarbage() {
   CollectGarbageInternal();
 }
diff --git a/src/heap.h b/src/heap.h
index e54135e..1059fd7 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -7,12 +7,13 @@
 #include <vector>
 
 #include "globals.h"
-#include "object.h"
 #include "object_bitmap.h"
 #include "thread.h"
 
 namespace art {
 
+class Class;
+class Object;
 class Space;
 class HeapBitmap;
 
@@ -30,43 +31,9 @@
 
   static void Destroy();
 
-  // Allocates and initializes storage for a class instance.
-  static Object* AllocObject(Class* klass);
-
+  // Allocates and initializes storage for an object instance.
   static Object* AllocObject(Class* klass, size_t num_bytes);
 
-  static Array* AllocArray(Class* array_class,
-                           size_t component_count,
-                           size_t component_size) {
-    size_t size = sizeof(Array) + component_count * component_size;
-    Array* array = down_cast<Array*>(AllocObject(array_class, size));
-    if (array != NULL) {
-      array->SetLength(component_count);
-    }
-    return array;
-  }
-
-  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) {
-    return down_cast<CharArray*>(AllocArray(char_array_class,
-                                            length,
-                                            sizeof(uint16_t)));
-  }
-
-  static String* AllocString(Class* java_lang_String) {
-    return down_cast<String*>(AllocObject(java_lang_String));
-  }
-
-  static String* AllocStringFromModifiedUtf8(Class* java_lang_String,
-                                             Class* char_array,
-                                             const char* data);
-
   // Initiates an explicit garbage collection.
   static void CollectGarbage();
 
diff --git a/src/object.cc b/src/object.cc
index 289f526..fbcfa8b 100644
--- a/src/object.cc
+++ b/src/object.cc
@@ -6,6 +6,7 @@
 #include <algorithm>
 
 #include "globals.h"
+#include "heap.h"
 #include "logging.h"
 #include "dex_cache.h"
 #include "dex_file.h"
diff --git a/src/object.h b/src/object.h
index bf965df..a154959 100644
--- a/src/object.h
+++ b/src/object.h
@@ -6,6 +6,7 @@
 #include "constants.h"
 #include "casts.h"
 #include "globals.h"
+#include "heap.h"
 #include "logging.h"
 #include "macros.h"
 #include "offsets.h"
@@ -104,6 +105,8 @@
 
 class Object {
  public:
+  static Object* Alloc(Class* klass);
+
   Class* GetClass() const {
     return klass_;
   }
@@ -563,6 +566,16 @@
 
 class Array : public Object {
  public:
+  static Array* Alloc(Class* array_class,
+                      size_t component_count,
+                      size_t component_size) {
+    size_t size = sizeof(Array) + component_count * component_size;
+    Array* array = down_cast<Array*>(Heap::AllocObject(array_class, size));
+    if (array != NULL) {
+      array->SetLength(component_count);
+    }
+    return array;
+  }
   uint32_t GetLength() const {
     return length_;
   }
@@ -587,21 +600,33 @@
 template<class T>
 class ObjectArray : public Array {
  public:
-  C* Get(uint32_t i) const {
+  static ObjectArray<T>* Alloc(Class* object_array_class,
+                               size_t length) {
+    return down_cast<ObjectArray<T>*>(Array::Alloc(object_array_class,
+                                                   length,
+                                                   sizeof(uint32_t)));
+  }
+
+  T* Get(uint32_t i) const {
     DCHECK_LT(i, GetLength());
     Object* const * data = reinterpret_cast<Object* const *>(GetData());
-    return down_cast<C*>(data[i]);
+    return down_cast<T*>(data[i]);
   }
-  void Set(uint32_t i, C* object) {
+  void Set(uint32_t i, T* object) {
     DCHECK_LT(i, GetLength());
-    C** data = reinterpret_cast<C**>(GetData());
+    T** data = reinterpret_cast<T**>(GetData());
     data[i] = object;
   }
-  static void Copy(ObjectArray<C>* src, int src_pos, ObjectArray<C>* dst, int dst_pos, size_t length) {
+  static void Copy(ObjectArray<T>* src, int src_pos, ObjectArray<T>* 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));
     }
   }
+  ObjectArray<T>* CopyOf(size_t new_length) {
+    ObjectArray<T>* new_array = Alloc(klass_, new_length);
+    Copy(this, 0, new_array, 0, std::min(GetLength(), new_length));
+    return new_array;
+  }
 
  private:
   ObjectArray();
@@ -945,6 +970,10 @@
 };
 std::ostream& operator<<(std::ostream& os, const Class::Status& rhs);
 
+inline Object* Object::Alloc(Class* klass) {
+  return Heap::AllocObject(klass, klass->object_size_);
+}
+
 class DataObject : public Object {
  public:
   uint32_t fields_[0];
@@ -953,12 +982,34 @@
 };
 
 class CharArray : public Array {
+ public:
+  static CharArray* Alloc(Class* char_array_class, size_t length) {
+    return down_cast<CharArray*>(Array::Alloc(char_array_class,
+                                              length,
+                                              sizeof(uint16_t)));
+  }
  private:
   CharArray();
 };
 
 class String : public Object {
  public:
+  static String* Alloc(Class* java_lang_String) {
+    return down_cast<String*>(Object::Alloc(java_lang_String));
+  }
+
+  static String* AllocFromModifiedUtf8(Class* java_lang_String,
+                                       Class* char_array,
+                                       const char* data) {
+    String* string = Alloc(java_lang_String);
+    uint32_t count = strlen(data);  // TODO
+    CharArray* array = CharArray::Alloc(char_array, count);
+    string->array_ = array;
+    string->count_ = count;
+    return string;
+  }
+
+ public: // TODO: private
   CharArray* array_;
 
   uint32_t hash_code_;
diff --git a/src/thread.h b/src/thread.h
index ed2ba12..d0f6623 100644
--- a/src/thread.h
+++ b/src/thread.h
@@ -11,7 +11,6 @@
 #include "jni_internal.h"
 #include "logging.h"
 #include "macros.h"
-#include "object.h"
 #include "offsets.h"
 #include "runtime.h"
 
@@ -19,6 +18,7 @@
 
 namespace art {
 
+class Method;
 class Object;
 class Runtime;
 class StackHandleBlock;