Add support for initializing static fields.

Change-Id: I1c5397e9ef03f4cef1646fa833e17d64fc586dce
diff --git a/src/class_linker.cc b/src/class_linker.cc
index 4924810..8e43135 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -6,7 +6,9 @@
 #include <vector>
 #include <utility>
 
+#include "src/casts.h"
 #include "src/dex_verifier.h"
+#include "src/heap.h"
 #include "src/logging.h"
 #include "src/monitor.h"
 #include "src/object.h"
@@ -30,7 +32,7 @@
       // No .dex file specified, search the class path.
       dex_file = FindInClassPath(descriptor);
       if (dex_file == NULL) {
-        LG << "Class really not found";
+        LG << "Class " << descriptor << " really not found";
         return NULL;
       }
     }
@@ -229,7 +231,7 @@
   } else {
     // JValue unused;
     // TODO: dvmCallMethod(self, method, NULL, &unused);
-    CHECK(!"unimplemented");
+    //CHECK(!"unimplemented");
   }
 
   {
@@ -357,10 +359,61 @@
 }
 
 void ClassLinker::InitializeStaticFields(Class* klass) {
-  if (klass->NumStaticFields() == 0) {
+  size_t num_static_fields = klass->NumStaticFields();
+  if (num_static_fields == 0) {
     return;
-  } else {
-    LOG(FATAL) << "Unimplemented";
+  }
+  DexFile* dex_file = klass->GetDexFile();
+  if (dex_file == NULL) {
+    return;
+  }
+  const char* descriptor = klass->GetDescriptor().data();
+  RawDexFile* raw = dex_file->GetRaw();
+  const RawDexFile::ClassDef* class_def = raw->FindClassDef(descriptor);
+  CHECK(class_def != NULL);
+  const byte* addr = raw->GetEncodedArray(*class_def);
+  size_t array_size = DecodeUnsignedLeb128(&addr);
+  for (size_t i = 0; i < array_size; ++i) {
+    StaticField* field = klass->GetStaticField(i);
+    JValue value;
+    RawDexFile::ValueType type = raw->ReadEncodedValue(&addr, &value);
+    switch (type) {
+      case RawDexFile::kByte:
+        field->SetByte(value.b);
+        break;
+      case RawDexFile::kShort:
+        field->SetShort(value.s);
+        break;
+      case RawDexFile::kChar:
+        field->SetChar(value.c);
+        break;
+      case RawDexFile::kInt:
+        field->SetInt(value.i);
+        break;
+      case RawDexFile::kLong:
+        field->SetLong(value.j);
+        break;
+      case RawDexFile::kFloat:
+        field->SetFloat(value.f);
+        break;
+      case RawDexFile::kDouble:
+        field->SetDouble(value.d);
+        break;
+      case RawDexFile::kString: {
+        uint32_t string_idx = value.i;
+        String* resolved = ResolveString(klass, string_idx);
+        field->SetObject(resolved);
+        break;
+      }
+      case RawDexFile::kBoolean:
+        field->SetBoolean(value.z);
+        break;
+      case RawDexFile::kNull:
+        field->SetObject(value.l);
+        break;
+      default:
+        LOG(FATAL) << "Unknown type " << type;
+    }
   }
 }
 
@@ -855,7 +908,7 @@
   }
 }
 
-Class* ClassLinker::ResolveClass(Class* referrer, uint32_t class_idx) {
+Class* ClassLinker::ResolveClass(const Class* referrer, uint32_t class_idx) {
   DexFile* dex_file = referrer->GetDexFile();
   Class* resolved = dex_file->GetResolvedClass(class_idx);
   if (resolved != NULL) {
@@ -875,7 +928,7 @@
         return NULL;
       }
     }
-    dex_file->SetResolvedClass(class_idx, resolved);
+    dex_file->SetResolvedClass(resolved, class_idx);
   } else {
     CHECK(Thread::Self()->IsExceptionPending());
   }
@@ -888,4 +941,14 @@
   return NULL;
 }
 
+String* ClassLinker::ResolveString(const Class* referring, uint32_t string_idx) {
+  const RawDexFile* raw = referring->GetDexFile()->GetRaw();
+  const RawDexFile::StringId& string_id = raw->GetStringId(string_idx);
+  const char* string_data = raw->GetStringData(string_id);
+  String* new_string = Heap::AllocStringFromModifiedUtf8(string_data);
+  // TODO: intern the new string
+  referring->GetDexFile()->SetResolvedString(new_string, string_idx);
+  return new_string;
+}
+
 }  // namespace art