Initialize ClassLinker from image

Change-Id: Ibaf47b4181f7c6603a8b37e2eba8fa6509c927ed
diff --git a/src/image_writer.cc b/src/image_writer.cc
index 4335a90..1c7acff 100644
--- a/src/image_writer.cc
+++ b/src/image_writer.cc
@@ -6,10 +6,12 @@
 #include <vector>
 
 #include "dex_cache.h"
+#include "class_linker.h"
 #include "file.h"
 #include "globals.h"
 #include "heap.h"
 #include "image.h"
+#include "intern_table.h"
 #include "logging.h"
 #include "object.h"
 #include "space.h"
@@ -43,6 +45,40 @@
   return true;
 }
 
+namespace {
+
+struct InternTableVisitorState {
+  int index;
+  ObjectArray<Object>* interned_array;
+};
+
+void InternTableVisitor(Object* obj, void* arg) {
+  InternTableVisitorState* state = reinterpret_cast<InternTableVisitorState*>(arg);
+  state->interned_array->Set(state->index++, obj);
+}
+
+ObjectArray<Object>* CreateInternedArray() {
+  // build a Object[] of the interned strings for reinit
+  // TODO: avoid creating this future garbage
+  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+  const InternTable& intern_table = class_linker->GetInternTable();
+  size_t size = intern_table.Size();
+  CHECK_NE(0U, size);
+
+  Class* object_array_class = class_linker->FindSystemClass("[Ljava/lang/Object;");
+  ObjectArray<Object>* interned_array = ObjectArray<Object>::Alloc(object_array_class, size);
+
+  InternTableVisitorState state;
+  state.index = 0;
+  state.interned_array = interned_array;
+
+  intern_table.VisitRoots(InternTableVisitor, &state);
+
+  return interned_array;
+}
+
+} // namespace
+
 void ImageWriter::CalculateNewObjectOffsetsCallback(Object *obj, void *arg) {
   DCHECK(obj != NULL);
   DCHECK(arg != NULL);
@@ -53,14 +89,24 @@
 }
 
 void ImageWriter::CalculateNewObjectOffsets() {
+  ObjectArray<Object>* interned_array = CreateInternedArray();
+
   HeapBitmap* heap_bitmap = Heap::GetLiveBits();
   DCHECK(heap_bitmap != NULL);
   DCHECK_EQ(0U, image_top_);
-  ImageHeader image_header(reinterpret_cast<uint32_t>(image_base_));
-  memcpy(image_->GetAddress(), &image_header, sizeof(image_header));
-  image_top_ += RoundUp(sizeof(image_header), 8); // 64-bit-alignment
+
+  // leave space for the header, but do not write it yet, we need to
+  // know where interned_array is going to end up
+  image_top_ += RoundUp(sizeof(ImageHeader), 8); // 64-bit-alignment
+
   heap_bitmap->Walk(CalculateNewObjectOffsetsCallback, this);
   DCHECK_LT(image_top_, image_->GetLength());
+
+  // return to write header at start of image with future location of interned_array
+  ImageHeader image_header(reinterpret_cast<uint32_t>(image_base_),
+                           reinterpret_cast<uint32_t>(GetImageAddress(interned_array)));
+  memcpy(image_->GetAddress(), &image_header, sizeof(image_header));
+
   // Note that top_ is left at end of used space
 }
 
@@ -92,6 +138,10 @@
   // TODO: special case init of pointers to malloc data (or removal of these pointers)
   if (orig->IsClass()) {
     FixupClass(orig->AsClass(), down_cast<Class*>(copy));
+  } else if (orig->IsMethod()) {
+    FixupMethod(orig->AsMethod(), down_cast<Method*>(copy));
+  } else if (orig->IsField()) {
+    FixupField(orig->AsField(), down_cast<Field*>(copy));
   } else if (orig->IsObjectArray()) {
     FixupObjectArray(orig->AsObjectArray<Object>(), down_cast<ObjectArray<Object>*>(copy));
   } else {
@@ -117,6 +167,20 @@
   copy->static_references_ = down_cast<ObjectArray<Object>*>(GetImageAddress(orig->static_references_));
 }
 
+// TODO: remove this slow path
+void ImageWriter::FixupMethod(Method* orig, Method* copy) {
+  FixupInstanceFields(orig, copy);
+  // TODO: remove need for this by adding "signature" to java.lang.reflect.Method
+  copy->signature_ = down_cast<String*>(GetImageAddress(orig->signature_));
+  DCHECK(copy->signature_ != NULL);
+  // TODO: convert shorty_ to heap allocated storage
+}
+
+void ImageWriter::FixupField(Field* orig, Field* copy) {
+  FixupInstanceFields(orig, copy);
+  // TODO: convert descriptor_ to heap allocated storage
+}
+
 void ImageWriter::FixupObjectArray(ObjectArray<Object>* orig, ObjectArray<Object>* copy) {
   for (int32_t i = 0; i < orig->GetLength(); ++i) {
     const Object* element = orig->Get(i);