Fix ClassLinker::InitializeStaticStorageFromCode

Previously the code computed the storage and returned the pointer to
it, but it forgot to set the value into the table for future
callers. Added a test to confirm the correct behavior.

Change-Id: I48717a3d4926f5ddc0ad09d065f75d031eb5b8fb
diff --git a/src/class_linker.cc b/src/class_linker.cc
index 9a6470b..8ddcc5f 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -1394,6 +1394,7 @@
     CHECK(Thread::Current()->IsExceptionPending());
     UNIMPLEMENTED(FATAL) << "throw exception due to class initializtion problem";
   }
+  referrer->GetDexCacheInitializedStaticStorage()->Set(type_idx, klass);
   return klass;
 }
 
diff --git a/src/class_linker_test.cc b/src/class_linker_test.cc
index 583c280..92b3fca 100644
--- a/src/class_linker_test.cc
+++ b/src/class_linker_test.cc
@@ -565,4 +565,20 @@
   EXPECT_EQ(Aj2, A->FindVirtualMethodForVirtualOrInterface(Jj2));
 }
 
+TEST_F(ClassLinkerTest, InitializeStaticStorageFromCode) {
+  // pretend we are trying to ensure we have initilized storage for Static from Statics.<clinit>
+  const ClassLoader* class_loader = LoadDex("Statics");
+  const DexFile* dex_file = ClassLoader::GetClassPath(class_loader)[0];
+  CHECK(dex_file != NULL);
+
+  Class* Statics = class_linker_->FindClass("LStatics;", class_loader);
+  Method* clinit = Statics->FindDirectMethod("<clinit>", "()V");
+  uint32_t type_idx = FindTypeIdxByDescriptor(*dex_file, "LStatics;");
+
+  EXPECT_TRUE(clinit->GetDexCacheInitializedStaticStorage()->Get(type_idx) == NULL);
+  StaticStorageBase* storage = class_linker_->InitializeStaticStorageFromCode(type_idx, clinit);
+  EXPECT_TRUE(storage != NULL);
+  EXPECT_EQ(storage, clinit->GetDexCacheInitializedStaticStorage()->Get(type_idx));
+}
+
 }  // namespace art
diff --git a/src/common_test.h b/src/common_test.h
index b4c1529..4689b28 100644
--- a/src/common_test.h
+++ b/src/common_test.h
@@ -171,6 +171,31 @@
     return DexFile::OpenZip(libcore_dex_file_name);
   }
 
+  uint32_t FindTypeIdxByDescriptor(const DexFile& dex_file, const StringPiece& descriptor) {
+    for (size_t i = 0; i < dex_file.NumTypeIds(); i++) {
+      const DexFile::TypeId& type_id = dex_file.GetTypeId(i);
+      if (descriptor == dex_file.GetTypeDescriptor(type_id)) {
+        return i;
+      }
+    }
+    CHECK(false) << "Could not find type index for " << descriptor;
+    return 0;
+  }
+
+  uint32_t FindFieldIdxByDescriptorAndName(const DexFile& dex_file,
+                                           const StringPiece& class_descriptor,
+                                           const StringPiece& field_name) {
+    for (size_t i = 0; i < dex_file.NumFieldIds(); i++) {
+      const DexFile::FieldId& field_id = dex_file.GetFieldId(i);
+      if (class_descriptor == dex_file.GetFieldClassDescriptor(field_id)
+          && field_name == dex_file.GetFieldName(field_id)) {
+        return i;
+      }
+    }
+    CHECK(false) << "Could not find field index for " << class_descriptor << " " << field_name;
+    return 0;
+  }
+
   const PathClassLoader* AllocPathClassLoader(const DexFile* dex_file) {
     CHECK(dex_file != NULL);
     class_linker_->RegisterDexFile(*dex_file);
diff --git a/src/object.h b/src/object.h
index a0f3e38..ca84dac 100644
--- a/src/object.h
+++ b/src/object.h
@@ -1170,13 +1170,13 @@
 }
 
 // Type for the InitializedStaticStorage table. Currently the Class
-// provides the static storage. However, this might change to improve
-// image sharing, so we use this type to avoid assumptions on the
-// current storage.
-class StaticStorageBase {};
+// provides the static storage. However, this might change to an Array
+// to improve image sharing, so we use this type to avoid assumptions
+// on the current storage.
+class StaticStorageBase : public Object {};
 
 // C++ mirror of java.lang.Class
-class Class : public Object, public StaticStorageBase {
+class Class : public StaticStorageBase {
  public:
 
   // Class Status
diff --git a/src/object_test.cc b/src/object_test.cc
index 79a1f2d..3c8ba5c 100644
--- a/src/object_test.cc
+++ b/src/object_test.cc
@@ -37,31 +37,6 @@
     }
     EXPECT_EQ(expected_hash, string->GetHashCode());
   }
-
-  uint32_t FindTypeIdxByDescriptor(const DexFile& dex_file, const StringPiece& descriptor) {
-    for (size_t i = 0; i < dex_file.NumTypeIds(); i++) {
-      const DexFile::TypeId& type_id = dex_file.GetTypeId(i);
-      if (descriptor == dex_file.GetTypeDescriptor(type_id)) {
-        return i;
-      }
-    }
-    CHECK(false) << "Could not find type index for " << descriptor;
-    return 0;
-  }
-
-  uint32_t FindFieldIdxByDescriptorAndName(const DexFile& dex_file,
-                                           const StringPiece& class_descriptor,
-                                           const StringPiece& field_name) {
-    for (size_t i = 0; i < dex_file.NumFieldIds(); i++) {
-      const DexFile::FieldId& field_id = dex_file.GetFieldId(i);
-      if (class_descriptor == dex_file.GetFieldClassDescriptor(field_id)
-          && field_name == dex_file.GetFieldName(field_id)) {
-        return i;
-      }
-    }
-    CHECK(false) << "Could not find field index for " << class_descriptor << " " << field_name;
-    return 0;
-  }
 };
 
 TEST_F(ObjectTest, IsInSamePackage) {
@@ -201,13 +176,16 @@
 }
 
 TEST_F(ObjectTest, StaticFieldFromCode) {
-  // pretend we are trying to access 'String.ASCII' from String.<clinit>
-  Class* java_lang_String = class_linker_->FindSystemClass("Ljava/lang/String;");
-  Method* clinit = java_lang_String->FindDirectMethod("<clinit>", "()V");
-  uint32_t field_idx = FindFieldIdxByDescriptorAndName(*java_lang_dex_file_.get(),
-                                                       "Ljava/lang/String;", "ASCII");
-  Object* ASCII = Field::GetObjStaticFromCode(field_idx, clinit);
-  EXPECT_EQ(NULL, ASCII);
+  // pretend we are trying to access 'Static.s8' from Statics.<clinit>
+  const ClassLoader* class_loader = LoadDex("Statics");
+  const DexFile* dex_file = ClassLoader::GetClassPath(class_loader)[0];
+  CHECK(dex_file != NULL);
+
+  Class* Statics = class_linker_->FindClass("LStatics;", class_loader);
+  Method* clinit = Statics->FindDirectMethod("<clinit>", "()V");
+  uint32_t field_idx = FindFieldIdxByDescriptorAndName(*dex_file, "LStatics;", "s8");
+  Object* s8 = Field::GetObjStaticFromCode(field_idx, clinit);
+  EXPECT_EQ(NULL, s8);
 
   CharArray* char_array = CharArray::Alloc(0);
   Field::SetObjStaticFromCode(field_idx, clinit, char_array);
@@ -217,7 +195,6 @@
   EXPECT_EQ(NULL, Field::GetObjStaticFromCode(field_idx, clinit));
 
   // TODO: more exhaustive tests of all 6 cases of Field::*FromCode
-  // TODO: test should not assume private internals such as String.ASCII field.
 }
 
 TEST_F(ObjectTest, String) {