Add InitializedStaticStorage table

A non-null entry in the table not only provides access to the storage,
it also implies that the referenced type is initialized.

Change-Id: Ief9e88b7e58b65b6f9456a4218b7fe87f71c17bb
diff --git a/src/class_linker.cc b/src/class_linker.cc
index 41a1c55..8236739 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -434,7 +434,8 @@
                   AllocObjectArray<Class>(dex_file.NumTypeIds()),
                   AllocObjectArray<Method>(dex_file.NumMethodIds()),
                   AllocObjectArray<Field>(dex_file.NumFieldIds()),
-                  AllocCodeAndDirectMethods(dex_file.NumMethodIds()));
+                  AllocCodeAndDirectMethods(dex_file.NumMethodIds()),
+                  AllocObjectArray<StaticStorageBase>(dex_file.NumTypeIds()));
   return dex_cache;
 }
 
@@ -767,10 +768,11 @@
   dst->access_flags_ = src.access_flags_;
 
   dst->dex_cache_strings_ = klass->dex_cache_->GetStrings();
-  dst->dex_cache_types_ = klass->dex_cache_->GetTypes();
-  dst->dex_cache_methods_ = klass->dex_cache_->GetMethods();
-  dst->dex_cache_fields_ = klass->dex_cache_->GetFields();
+  dst->dex_cache_resolved_types_ = klass->dex_cache_->GetResolvedTypes();
+  dst->dex_cache_resolved_methods_ = klass->dex_cache_->GetResolvedMethods();
+  dst->dex_cache_resolved_fields_ = klass->dex_cache_->GetResolvedFields();
   dst->dex_cache_code_and_direct_methods_ = klass->dex_cache_->GetCodeAndDirectMethods();
+  dst->dex_cache_initialized_static_storage_ = klass->dex_cache_->GetInitializedStaticStorage();
 
   dst->is_direct_ = is_direct;
 
@@ -1277,6 +1279,19 @@
   return !Thread::Current()->IsExceptionPending();
 }
 
+StaticStorageBase* ClassLinker::InitializeStaticStorageFromCode(uint32_t type_idx, Method* referrer) {
+  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+  Class* klass = class_linker->ResolveType(type_idx, referrer);
+  if (klass == NULL) {
+    UNIMPLEMENTED(FATAL) << "throw exception due to unresolved class";
+  }
+  if (!class_linker->EnsureInitialized(klass)) {
+    CHECK(Thread::Current()->IsExceptionPending());
+    UNIMPLEMENTED(FATAL) << "throw exception due to class initializtion problem";
+  }
+  return klass;
+}
+
 void ClassLinker::InitializeStaticFields(Class* klass) {
   size_t num_static_fields = klass->NumStaticFields();
   if (num_static_fields == 0) {
diff --git a/src/class_linker.h b/src/class_linker.h
index 5e3ac78..d9716ee 100644
--- a/src/class_linker.h
+++ b/src/class_linker.h
@@ -78,6 +78,8 @@
                      DexCache* dex_cache,
                      const ClassLoader* class_loader);
 
+  static StaticStorageBase* InitializeStaticStorageFromCode(uint32_t type_idx, Method* referrer);
+
   // Resolve a method with a given ID from the DexFile, storing the
   // result in DexCache. The ClassLinker and ClassLoader are used as
   // in ResolveType. What is unique is the method type argument which
diff --git a/src/class_linker_test.cc b/src/class_linker_test.cc
index 9fd5fb5..8de8ba1 100644
--- a/src/class_linker_test.cc
+++ b/src/class_linker_test.cc
@@ -102,16 +102,23 @@
     EXPECT_TRUE(method->GetSignature() != NULL);
 
     EXPECT_TRUE(method->dex_cache_strings_ != NULL);
-    EXPECT_TRUE(method->dex_cache_types_ != NULL);
-    EXPECT_TRUE(method->dex_cache_methods_ != NULL);
-    EXPECT_TRUE(method->dex_cache_fields_ != NULL);
+    EXPECT_TRUE(method->dex_cache_resolved_types_ != NULL);
+    EXPECT_TRUE(method->dex_cache_resolved_methods_ != NULL);
+    EXPECT_TRUE(method->dex_cache_resolved_fields_ != NULL);
     EXPECT_TRUE(method->dex_cache_code_and_direct_methods_ != NULL);
-    EXPECT_EQ(method->declaring_class_->dex_cache_->GetStrings(), method->dex_cache_strings_);
-    EXPECT_EQ(method->declaring_class_->dex_cache_->GetTypes(), method->dex_cache_types_);
-    EXPECT_EQ(method->declaring_class_->dex_cache_->GetMethods(), method->dex_cache_methods_);
-    EXPECT_EQ(method->declaring_class_->dex_cache_->GetFields(), method->dex_cache_fields_);
+    EXPECT_TRUE(method->dex_cache_initialized_static_storage_ != NULL);
+    EXPECT_EQ(method->declaring_class_->dex_cache_->GetStrings(),
+              method->dex_cache_strings_);
+    EXPECT_EQ(method->declaring_class_->dex_cache_->GetResolvedTypes(),
+              method->dex_cache_resolved_types_);
+    EXPECT_EQ(method->declaring_class_->dex_cache_->GetResolvedMethods(),
+              method->dex_cache_resolved_methods_);
+    EXPECT_EQ(method->declaring_class_->dex_cache_->GetResolvedFields(),
+              method->dex_cache_resolved_fields_);
     EXPECT_EQ(method->declaring_class_->dex_cache_->GetCodeAndDirectMethods(),
               method->dex_cache_code_and_direct_methods_);
+    EXPECT_EQ(method->declaring_class_->dex_cache_->GetInitializedStaticStorage(),
+              method->dex_cache_initialized_static_storage_);
   }
 
   void AssertField(Class* klass, Field* field) {
diff --git a/src/compiler.cc b/src/compiler.cc
index c8ff794..7644444 100644
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -40,17 +40,17 @@
   }
 
   // Class derived values are more complicated, they require the linker and loader
-  for (size_t i = 0; i < dex_cache->NumTypes(); i++) {
+  for (size_t i = 0; i < dex_cache->NumResolvedTypes(); i++) {
     class_linker->ResolveType(dex_file, i, dex_cache, class_loader);
   }
-  for (size_t i = 0; i < dex_cache->NumMethods(); i++) {
+  for (size_t i = 0; i < dex_cache->NumResolvedMethods(); i++) {
     // unknown if direct or virtual, try both
     Method* method = class_linker->ResolveMethod(dex_file, i, dex_cache, class_loader, false);
     if (method == NULL) {
       class_linker->ResolveMethod(dex_file, i, dex_cache, class_loader, true);
     }
   }
-  for (size_t i = 0; i < dex_cache->NumFields(); i++) {
+  for (size_t i = 0; i < dex_cache->NumResolvedFields(); i++) {
     // unknown if instance or static, try both
     Field* field = class_linker->ResolveField(dex_file, i, dex_cache, class_loader, false);
     if (field == NULL) {
@@ -117,7 +117,7 @@
   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
   DexCache* dex_cache = class_linker->FindDexCache(dex_file);
   CodeAndDirectMethods* code_and_direct_methods = dex_cache->GetCodeAndDirectMethods();
-  for (size_t i = 0; i < dex_cache->NumMethods(); i++) {
+  for (size_t i = 0; i < dex_cache->NumResolvedMethods(); i++) {
     Method* method = dex_cache->GetResolvedMethod(i);
     if (method == NULL) {
       code_and_direct_methods->SetResolvedDirectMethodTrampoline(i);
diff --git a/src/compiler/codegen/arm/MethodCodegenDriver.cc b/src/compiler/codegen/arm/MethodCodegenDriver.cc
index c83a2a4..bd50742 100644
--- a/src/compiler/codegen/arm/MethodCodegenDriver.cc
+++ b/src/compiler/codegen/arm/MethodCodegenDriver.cc
@@ -346,7 +346,7 @@
             break;
         case 3:  // Method->DeclaringClass()->GetDexCache()->methodsObjectArr
             loadBaseDisp(cUnit, mir, r0,
-                         art::DexCache::MethodsOffset().Int32Value(), r0,
+                         art::DexCache::ResolvedMethodsOffset().Int32Value(), r0,
                          kWord, INVALID_SREG);
             break;
         case 4: // Skip past the object header
@@ -444,7 +444,7 @@
             break;
         case 3:  // ...()->GetDexCache()->methodsObjectArr [uses/sets r0]
             loadBaseDisp(cUnit, mir, r0,
-                         art::DexCache::MethodsOffset().Int32Value(), r0,
+                         art::DexCache::ResolvedMethodsOffset().Int32Value(), r0,
                          kWord, INVALID_SREG);
             // Load "this" [set r1]
             rlArg = oatGetSrc(cUnit, mir, 0);
diff --git a/src/compiler_test.cc b/src/compiler_test.cc
index 8ab45b5..1e9f203 100644
--- a/src/compiler_test.cc
+++ b/src/compiler_test.cc
@@ -79,18 +79,18 @@
     String* string = dex_cache->GetResolvedString(i);
     EXPECT_TRUE(string != NULL);
   }
-  EXPECT_EQ(dex->NumTypeIds(), dex_cache->NumTypes());
-  for (size_t i = 0; i < dex_cache->NumTypes(); i++) {
+  EXPECT_EQ(dex->NumTypeIds(), dex_cache->NumResolvedTypes());
+  for (size_t i = 0; i < dex_cache->NumResolvedTypes(); i++) {
     Class* type = dex_cache->GetResolvedType(i);
     EXPECT_TRUE(type != NULL);
   }
-  EXPECT_EQ(dex->NumMethodIds(), dex_cache->NumMethods());
-  for (size_t i = 0; i < dex_cache->NumMethods(); i++) {
+  EXPECT_EQ(dex->NumMethodIds(), dex_cache->NumResolvedMethods());
+  for (size_t i = 0; i < dex_cache->NumResolvedMethods(); i++) {
     Method* method = dex_cache->GetResolvedMethod(i);
     EXPECT_TRUE(method != NULL);
   }
-  EXPECT_EQ(dex->NumFieldIds(), dex_cache->NumFields());
-  for (size_t i = 0; i < dex_cache->NumFields(); i++) {
+  EXPECT_EQ(dex->NumFieldIds(), dex_cache->NumResolvedFields());
+  for (size_t i = 0; i < dex_cache->NumResolvedFields(); i++) {
     Field* field = dex_cache->GetResolvedField(i);
     EXPECT_TRUE(field != NULL);
   }
diff --git a/src/dex_cache.cc b/src/dex_cache.cc
index a4538c9..d24c436 100644
--- a/src/dex_cache.cc
+++ b/src/dex_cache.cc
@@ -11,22 +11,25 @@
 
 void DexCache::Init(String* location,
                     ObjectArray<String>* strings,
-                    ObjectArray<Class>* types,
-                    ObjectArray<Method>* methods,
-                    ObjectArray<Field>* fields,
-                    CodeAndDirectMethods* code_and_direct_methods) {
+                    ObjectArray<Class>* resolved_types,
+                    ObjectArray<Method>* resolved_methods,
+                    ObjectArray<Field>* resolved_fields,
+                    CodeAndDirectMethods* code_and_direct_methods,
+                    ObjectArray<StaticStorageBase>* initialized_static_storage) {
   CHECK(location != NULL);
   CHECK(strings != NULL);
-  CHECK(types != NULL);
-  CHECK(methods != NULL);
-  CHECK(fields != NULL);
+  CHECK(resolved_types != NULL);
+  CHECK(resolved_methods != NULL);
+  CHECK(resolved_fields != NULL);
   CHECK(code_and_direct_methods != NULL);
-  Set(kLocation,       location);
-  Set(kStrings,        strings);
-  Set(kTypes,          types);
-  Set(kMethods,        methods);
-  Set(kFields,         fields);
-  Set(kCodeAndDirectMethods, code_and_direct_methods);
+  CHECK(initialized_static_storage != NULL);
+  Set(kLocation,                 location);
+  Set(kStrings,                  strings);
+  Set(kResolvedTypes,            resolved_types);
+  Set(kResolvedMethods,          resolved_methods);
+  Set(kResolvedFields,           resolved_fields);
+  Set(kCodeAndDirectMethods,     code_and_direct_methods);
+  Set(kInitializedStaticStorage, initialized_static_storage);
 }
 
 }  // namespace art
diff --git a/src/dex_cache.h b/src/dex_cache.h
index 1e46a90..0d217bc 100644
--- a/src/dex_cache.h
+++ b/src/dex_cache.h
@@ -43,6 +43,10 @@
    return kMax * elements;
  }
 
+ size_t NumCodeAndDirectMethods() const {
+   return GetLength() / kMax;
+ }
+
  private:
   enum TupleIndex {
     kCode   = 0,
@@ -59,7 +63,8 @@
             ObjectArray<Class>* types,
             ObjectArray<Method>* methods,
             ObjectArray<Field>* fields,
-            CodeAndDirectMethods* code_and_direct_methods);
+            CodeAndDirectMethods* code_and_direct_methods,
+            ObjectArray<StaticStorageBase>* initialized_static_storage);
 
   String* GetLocation() const {
     return Get(kLocation)->AsString();
@@ -70,34 +75,38 @@
                         kStrings * sizeof(Object*));
   }
 
-  static MemberOffset FieldsOffset() {
+  static MemberOffset ResolvedFieldsOffset() {
     return MemberOffset(DataOffset().Int32Value() +
-                        kFields * sizeof(Object*));
+                        kResolvedFields * sizeof(Object*));
   }
 
-  static MemberOffset MethodsOffset() {
+  static MemberOffset ResolvedMethodsOffset() {
     return MemberOffset(DataOffset().Int32Value() +
-                        kMethods * sizeof(Object*));
+                        kResolvedMethods * sizeof(Object*));
   }
 
   size_t NumStrings() const {
     return GetStrings()->GetLength();
   }
 
-  size_t NumTypes() const {
-    return GetTypes()->GetLength();
+  size_t NumResolvedTypes() const {
+    return GetResolvedTypes()->GetLength();
   }
 
-  size_t NumMethods() const {
-    return GetMethods()->GetLength();
+  size_t NumResolvedMethods() const {
+    return GetResolvedMethods()->GetLength();
   }
 
-  size_t NumFields() const {
-    return GetFields()->GetLength();
+  size_t NumResolvedFields() const {
+    return GetResolvedFields()->GetLength();
   }
 
   size_t NumCodeAndDirectMethods() const {
-    return GetCodeAndDirectMethods()->GetLength();
+    return GetCodeAndDirectMethods()->NumCodeAndDirectMethods();
+  }
+
+  size_t NumInitializedStaticStorage() const {
+    return GetInitializedStaticStorage()->GetLength();
   }
 
   String* GetResolvedString(uint32_t string_idx) const {
@@ -109,44 +118,47 @@
   }
 
   Class* GetResolvedType(uint32_t type_idx) const {
-    return GetTypes()->Get(type_idx);
+    return GetResolvedTypes()->Get(type_idx);
   }
 
   void SetResolvedType(uint32_t type_idx, Class* resolved) {
-    GetTypes()->Set(type_idx, resolved);
+    GetResolvedTypes()->Set(type_idx, resolved);
   }
 
   Method* GetResolvedMethod(uint32_t method_idx) const {
-    return GetMethods()->Get(method_idx);
+    return GetResolvedMethods()->Get(method_idx);
   }
 
   void SetResolvedMethod(uint32_t method_idx, Method* resolved) {
-    GetMethods()->Set(method_idx, resolved);
+    GetResolvedMethods()->Set(method_idx, resolved);
   }
 
   Field* GetResolvedField(uint32_t field_idx) const {
-    return GetFields()->Get(field_idx);
+    return GetResolvedFields()->Get(field_idx);
   }
 
   void SetResolvedfield(uint32_t field_idx, Field* resolved) {
-    GetFields()->Set(field_idx, resolved);
+    GetResolvedFields()->Set(field_idx, resolved);
   }
 
   ObjectArray<String>* GetStrings() const {
     return static_cast<ObjectArray<String>*>(GetNonNull(kStrings));
   }
-  ObjectArray<Class>* GetTypes() const {
-    return static_cast<ObjectArray<Class>*>(GetNonNull(kTypes));
+  ObjectArray<Class>* GetResolvedTypes() const {
+    return static_cast<ObjectArray<Class>*>(GetNonNull(kResolvedTypes));
   }
-  ObjectArray<Method>* GetMethods() const {
-    return static_cast<ObjectArray<Method>*>(GetNonNull(kMethods));
+  ObjectArray<Method>* GetResolvedMethods() const {
+    return static_cast<ObjectArray<Method>*>(GetNonNull(kResolvedMethods));
   }
-  ObjectArray<Field>* GetFields() const {
-    return static_cast<ObjectArray<Field>*>(GetNonNull(kFields));
+  ObjectArray<Field>* GetResolvedFields() const {
+    return static_cast<ObjectArray<Field>*>(GetNonNull(kResolvedFields));
   }
   CodeAndDirectMethods* GetCodeAndDirectMethods() const {
     return static_cast<CodeAndDirectMethods*>(GetNonNull(kCodeAndDirectMethods));
   }
+  ObjectArray<StaticStorageBase>* GetInitializedStaticStorage() const {
+    return static_cast<ObjectArray<StaticStorageBase>*>(GetNonNull(kInitializedStaticStorage));
+  }
 
  static size_t LengthAsArray() {
    return kMax;
@@ -155,13 +167,14 @@
  private:
 
   enum ArrayIndex {
-    kLocation             = 0,
-    kStrings              = 1,
-    kTypes                = 2,
-    kMethods              = 3,
-    kFields               = 4,
-    kCodeAndDirectMethods = 5,
-    kMax                  = 6,
+    kLocation                 = 0,
+    kStrings                  = 1,
+    kResolvedTypes            = 2,
+    kResolvedMethods          = 3,
+    kResolvedFields           = 4,
+    kCodeAndDirectMethods     = 5,
+    kInitializedStaticStorage = 6,
+    kMax                      = 7,
   };
 
   Object* GetNonNull(ArrayIndex array_index) const {
diff --git a/src/dex_cache_test.cc b/src/dex_cache_test.cc
index 6ecaa18..4c0939a 100644
--- a/src/dex_cache_test.cc
+++ b/src/dex_cache_test.cc
@@ -20,23 +20,31 @@
   ASSERT_TRUE(dex_cache != NULL);
 
   EXPECT_EQ(java_lang_dex_file_->NumStringIds(), dex_cache->NumStrings());
-  EXPECT_EQ(java_lang_dex_file_->NumTypeIds(),   dex_cache->NumTypes());
-  EXPECT_EQ(java_lang_dex_file_->NumMethodIds(), dex_cache->NumMethods());
-  EXPECT_EQ(java_lang_dex_file_->NumFieldIds(),  dex_cache->NumFields());
+  EXPECT_EQ(java_lang_dex_file_->NumTypeIds(),   dex_cache->NumResolvedTypes());
+  EXPECT_EQ(java_lang_dex_file_->NumMethodIds(), dex_cache->NumResolvedMethods());
+  EXPECT_EQ(java_lang_dex_file_->NumFieldIds(),  dex_cache->NumResolvedFields());
+  EXPECT_EQ(java_lang_dex_file_->NumMethodIds(), dex_cache->NumCodeAndDirectMethods());
+  EXPECT_EQ(java_lang_dex_file_->NumTypeIds(),   dex_cache->NumInitializedStaticStorage());
 
   EXPECT_LE(0, dex_cache->GetStrings()->GetLength());
-  EXPECT_LE(0, dex_cache->GetTypes()->GetLength());
-  EXPECT_LE(0, dex_cache->GetMethods()->GetLength());
-  EXPECT_LE(0, dex_cache->GetFields()->GetLength());
+  EXPECT_LE(0, dex_cache->GetResolvedTypes()->GetLength());
+  EXPECT_LE(0, dex_cache->GetResolvedMethods()->GetLength());
+  EXPECT_LE(0, dex_cache->GetResolvedFields()->GetLength());
+  EXPECT_LE(0, dex_cache->GetCodeAndDirectMethods()->GetLength());
+  EXPECT_LE(0, dex_cache->GetInitializedStaticStorage()->GetLength());
 
   EXPECT_EQ(java_lang_dex_file_->NumStringIds(),
             static_cast<uint32_t>(dex_cache->GetStrings()->GetLength()));
   EXPECT_EQ(java_lang_dex_file_->NumTypeIds(),
-            static_cast<uint32_t>(dex_cache->GetTypes()->GetLength()));
+            static_cast<uint32_t>(dex_cache->GetResolvedTypes()->GetLength()));
   EXPECT_EQ(java_lang_dex_file_->NumMethodIds(),
-            static_cast<uint32_t>(dex_cache->GetMethods()->GetLength()));
+            static_cast<uint32_t>(dex_cache->GetResolvedMethods()->GetLength()));
   EXPECT_EQ(java_lang_dex_file_->NumFieldIds(),
-            static_cast<uint32_t>(dex_cache->GetFields()->GetLength()));
+            static_cast<uint32_t>(dex_cache->GetResolvedFields()->GetLength()));
+  EXPECT_EQ(java_lang_dex_file_->NumMethodIds(),
+            static_cast<uint32_t>(dex_cache->GetCodeAndDirectMethods()->NumCodeAndDirectMethods()));
+  EXPECT_EQ(java_lang_dex_file_->NumTypeIds(),
+            static_cast<uint32_t>(dex_cache->GetInitializedStaticStorage()->GetLength()));
 }
 
 }  // namespace art
diff --git a/src/object.cc b/src/object.cc
index 7328dbe..f938bc2 100644
--- a/src/object.cc
+++ b/src/object.cc
@@ -31,7 +31,8 @@
 }
 
 Array* Array::AllocFromCode(uint32_t type_idx, Method* method, int32_t component_count) {
-  Class* klass = method->dex_cache_types_->Get(type_idx);
+  // TODO: throw on negative component_count
+  Class* klass = method->dex_cache_resolved_types_->Get(type_idx);
   if (klass == NULL) {
     klass = Runtime::Current()->GetClassLinker()->ResolveType(type_idx, method);
     if (klass == NULL || !klass->IsArrayClass()) {
@@ -43,7 +44,7 @@
 }
 
 Object* Class::NewInstanceFromCode(uint32_t type_idx, Method* method) {
-  Class* klass = method->dex_cache_types_->Get(type_idx);
+  Class* klass = method->dex_cache_resolved_types_->Get(type_idx);
   if (klass == NULL) {
     klass = Runtime::Current()->GetClassLinker()->ResolveType(type_idx, method);
     if (klass == NULL) {
diff --git a/src/object.h b/src/object.h
index 51bf999..d299c5b 100644
--- a/src/object.h
+++ b/src/object.h
@@ -25,6 +25,7 @@
 class Monitor;
 class Method;
 class Object;
+class StaticStorageBase;
 class String;
 template<class T> class ObjectArray;
 template<class T> class PrimitiveArray;
@@ -720,10 +721,11 @@
   // short cuts to declaring_class_->dex_cache_ members for fast compiled code
   // access
   ObjectArray<String>* dex_cache_strings_;
-  ObjectArray<Class>* dex_cache_types_;
-  ObjectArray<Method>* dex_cache_methods_;
-  ObjectArray<Field>* dex_cache_fields_;
+  ObjectArray<Class>* dex_cache_resolved_types_;
+  ObjectArray<Method>* dex_cache_resolved_methods_;
+  ObjectArray<Field>* dex_cache_resolved_fields_;
   CodeAndDirectMethods* dex_cache_code_and_direct_methods_;
+  ObjectArray<StaticStorageBase>* dex_cache_initialized_static_storage_;
 
   bool is_direct_;
 
@@ -899,8 +901,14 @@
   DISALLOW_IMPLICIT_CONSTRUCTORS(PathClassLoader);
 };
 
+// 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 {};
+
 // Class objects.
-class Class : public Object {
+class Class : public Object, public StaticStorageBase {
  public:
 
   // Class Status