Mark non-image spaces and use write barrier for image spaces.

Don't mark string and class roots that are in the image, alloc space
references will be caught by the write barrier.

Change-Id: Idcf9e4ede3b83556d4f8a01276273726dc6eea46
diff --git a/src/class_linker.cc b/src/class_linker.cc
index 8f4029a..7dc0b7d 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -779,7 +779,8 @@
     // restore class to ClassLinker::classes_ table
     Class* klass = obj->AsClass();
     std::string descriptor = klass->GetDescriptor()->ToModifiedUtf8();
-    class_linker->InsertClass(descriptor, klass);
+    bool success = class_linker->InsertClass(descriptor, klass, true);
+    DCHECK(success);
     return;
   }
 }
@@ -800,6 +801,7 @@
     for (It it = classes_.begin(), end = classes_.end(); it != end; ++it) {
       visitor(it->second, arg);
     }
+    // Note. we deliberately ignore the class roots in the image (held in image_classes_)
   }
 
   visitor(array_interfaces_, arg);
@@ -1026,7 +1028,7 @@
   ObjectLock lock(klass.get());
   klass->SetClinitThreadId(self->GetTid());
   // Add the newly loaded class to the loaded classes table.
-  bool success = InsertClass(descriptor, klass.get());  // TODO: just return collision
+  bool success = InsertClass(descriptor, klass.get(), false);  // TODO: just return collision
   if (!success) {
     // We may fail to insert if we raced with another thread.
     klass->SetClinitThreadId(0);
@@ -1450,7 +1452,7 @@
   CHECK(primitive_class->GetDescriptor() != NULL);
   primitive_class->SetPrimitiveType(type);
   primitive_class->SetStatus(Class::kStatusInitialized);
-  bool success = InsertClass(descriptor, primitive_class);
+  bool success = InsertClass(descriptor, primitive_class, false);
   CHECK(success) << "InitPrimitiveClass(" << descriptor << ") failed";
   return primitive_class;
 }
@@ -1578,7 +1580,7 @@
   new_class->SetAccessFlags(((new_class->GetComponentType()->GetAccessFlags() &
                              ~kAccInterface) | kAccFinal) & kAccJavaFlagsMask);
 
-  if (InsertClass(descriptor, new_class.get())) {
+  if (InsertClass(descriptor, new_class.get(), false)) {
     return new_class.get();
   }
   // Another thread must have loaded the class after we
@@ -1621,10 +1623,17 @@
   return NULL;
 }
 
-bool ClassLinker::InsertClass(const std::string& descriptor, Class* klass) {
+bool ClassLinker::InsertClass(const std::string& descriptor, Class* klass, bool image_class) {
   size_t hash = StringPieceHash()(descriptor);
   MutexLock mu(classes_lock_);
-  Table::iterator it = classes_.insert(std::make_pair(hash, klass));
+  Table::iterator it;
+  if (image_class) {
+    // TODO: sanity check there's no match in classes_
+    it = image_classes_.insert(std::make_pair(hash, klass));
+  } else {
+    // TODO: sanity check there's no match in image_classes_
+    it = classes_.insert(std::make_pair(hash, klass));
+  }
   return ((*it).second == klass);
 }
 
@@ -1632,12 +1641,19 @@
   size_t hash = StringPieceHash()(descriptor);
   MutexLock mu(classes_lock_);
   typedef Table::const_iterator It;  // TODO: C++0x auto
+  // TODO: determine if its better to search classes_ or image_classes_ first
   for (It it = classes_.find(hash), end = classes_.end(); it != end; ++it) {
     Class* klass = it->second;
     if (klass->GetDescriptor()->Equals(descriptor) && klass->GetClassLoader() == class_loader) {
       return klass;
     }
   }
+  for (It it = image_classes_.find(hash), end = image_classes_.end(); it != end; ++it) {
+    Class* klass = it->second;
+    if (klass->GetDescriptor()->Equals(descriptor) && klass->GetClassLoader() == class_loader) {
+      return klass;
+    }
+  }
   return NULL;
 }
 
@@ -2772,6 +2788,9 @@
     for (It it = classes_.begin(), end = classes_.end(); it != end; ++it) {
       all_classes.push_back(it->second);
     }
+    for (It it = image_classes_.begin(), end = image_classes_.end(); it != end; ++it) {
+      all_classes.push_back(it->second);
+    }
   }
 
   for (size_t i = 0; i < all_classes.size(); ++i) {
@@ -2781,7 +2800,7 @@
 
 size_t ClassLinker::NumLoadedClasses() const {
   MutexLock mu(classes_lock_);
-  return classes_.size();
+  return classes_.size() + image_classes_.size();
 }
 
 pid_t ClassLinker::GetClassesLockOwner() {