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
diff --git a/src/class_linker.h b/src/class_linker.h
index 2021705..fec3cb1 100644
--- a/src/class_linker.h
+++ b/src/class_linker.h
@@ -29,7 +29,9 @@
 
   Class* LookupClass(const char* descriptor, Object* class_loader);
 
-  Class* ResolveClass(Class* klass, uint32_t idx);
+  Class* ResolveClass(const Class* referring, uint32_t class_idx);
+
+  String* ResolveString(const Class* referring, uint32_t string_idx);
 
   DexFile* FindInClassPath(const char* descriptor);
 
diff --git a/src/dex_file.cc b/src/dex_file.cc
index 9526b5a..fcde266 100644
--- a/src/dex_file.cc
+++ b/src/dex_file.cc
@@ -110,7 +110,7 @@
     for (size_t i = 0; i < klass->NumInstanceFields(); ++i) {
       RawDexFile::Field raw_field;
       raw_->dexReadClassDataField(&class_data, &raw_field, &last_idx);
-      LoadField(klass, raw_field, &klass->ifields_[i]);
+      LoadField(klass, raw_field, klass->GetInstanceField(i));
     }
   }
 
@@ -177,7 +177,7 @@
 
   // TODO: check for finalize method
 
-  const RawDexFile::Code* code_item = raw_->GetCode(src);
+  const RawDexFile::CodeItem* code_item = raw_->GetCodeItem(src);
   if (code_item != NULL) {
     dst->num_registers_ = code_item->registers_size_;
     dst->num_ins_ = code_item->ins_size_;
diff --git a/src/dex_file.h b/src/dex_file.h
index 07650c2..ae5101a 100644
--- a/src/dex_file.h
+++ b/src/dex_file.h
@@ -13,6 +13,7 @@
 class Field;
 class Method;
 class String;
+union JValue;
 
 class DexFile {
  public:
@@ -51,11 +52,19 @@
     return raw_.get();
   }
 
+  String* GetResolvedString(uint32_t string_idx) const {
+    return strings_[string_idx];
+  }
+
+  void SetResolvedString(String* resolved, uint32_t string_idx) {
+    strings_[string_idx] = resolved;
+  }
+
   Class* GetResolvedClass(uint32_t class_idx) const {
     return classes_[class_idx];
   }
 
-  void SetResolvedClass(uint32_t class_idx, Class* resolved) {
+  void SetResolvedClass(Class* resolved, uint32_t class_idx) {
     classes_[class_idx] = resolved;
   }
 
diff --git a/src/heap.h b/src/heap.h
index 340e51c..c04a60f 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -12,10 +12,30 @@
 class Heap {
  public:
   static Class* AllocClass(size_t size) {
-    byte* raw = new byte[size];
-    memset(raw, 0, size);
+    byte* raw = new byte[size]();
     return reinterpret_cast<Class*>(raw);
   }
+
+  static CharArray* AllocCharArray(size_t length) {
+    size_t size = sizeof(Array) + length * sizeof(uint16_t);
+    byte* raw = new byte[size]();
+    return reinterpret_cast<CharArray*>(raw);
+  }
+
+  static String* AllocString() {
+    size_t size = sizeof(String);
+    byte* raw = new byte[size]();
+    return reinterpret_cast<String*>(raw);
+  }
+
+  static String* AllocStringFromModifiedUtf8(const char* data) {
+    String* string = AllocString();
+    uint32_t count = strlen(data);  // TODO
+    CharArray* array = AllocCharArray(count);
+    string->array_ = array;
+    string->count_ = count;
+    return string;
+  }
 };
 
 }  // namespace art
diff --git a/src/object.h b/src/object.h
index 98e464a..8252de1 100644
--- a/src/object.h
+++ b/src/object.h
@@ -187,6 +187,10 @@
     return signature_[0];
   }
 
+  const char* GetSignature() const {
+    return signature_;
+  }
+
  public:  // TODO: private
   // The class in which this field is declared.
   Class* klass_;
@@ -224,6 +228,58 @@
 
 // Static fields.
 class StaticField : public Field {
+ public:
+  void SetBoolean(bool z) {
+    CHECK_EQ(GetType(), 'Z');
+    value_.z = z;
+  }
+
+  void SetByte(int8_t b) {
+    CHECK_EQ(GetType(), 'B');
+    value_.b = b;
+  }
+
+  void SetChar(uint16_t c) {
+    CHECK_EQ(GetType(), 'C');
+    value_.c = c;
+  }
+
+  void SetShort(uint16_t s) {
+    CHECK_EQ(GetType(), 'S');
+    value_.s = s;
+  }
+
+  void SetInt(int32_t i) {
+    CHECK_EQ(GetType(), 'I');
+    value_.i = i;
+  }
+
+  int64_t GetLong() {
+    CHECK_EQ(GetType(), 'J');
+    return value_.j;
+  }
+
+  void SetLong(int64_t j) {
+    CHECK_EQ(GetType(), 'J');
+    value_.j = j;
+  }
+
+  void SetFloat(float f) {
+    CHECK_EQ(GetType(), 'F');
+    value_.f = f;
+  }
+
+  void SetDouble(double d) {
+    CHECK_EQ(GetType(), 'D');
+    value_.d = d;
+  }
+
+  void SetObject(Object* l) {
+    CHECK_EQ(GetType(), 'L');
+    value_.l = l;
+    // TODO: write barrier
+  }
+
  private:
   JValue value_;
 };
@@ -642,9 +698,22 @@
   uint32_t fields_[1];
 };
 
+class Array : public Object {
+ public:
+  void SetLength(uint32_t length) {
+    length_ = length;
+  }
+
+ private:
+  // The number of array elements.
+  uint32_t length_;
+};
+
+class CharArray : public Array {};
+
 class String : public Object {
  public:
-  Array* array_;
+  CharArray* array_;
 
   uint32_t hash_code_;
 
@@ -653,12 +722,6 @@
   uint32_t count_;
 };
 
-class Array : public Object {
- public:
-  // The number of array elements.
-  uint32_t length_;
-};
-
 class InterfaceEntry {
  public:
   Class* GetClass() const {
diff --git a/src/raw_dex_file.cc b/src/raw_dex_file.cc
index 9994b9f..145509a 100644
--- a/src/raw_dex_file.cc
+++ b/src/raw_dex_file.cc
@@ -1,10 +1,6 @@
 // Copyright 2011 Google Inc. All Rights Reserved.
 
-#include "src/base64.h"
-#include "src/globals.h"
-#include "src/logging.h"
 #include "src/raw_dex_file.h"
-#include "src/scoped_ptr.h"
 
 #include <errno.h>
 #include <fcntl.h>
@@ -14,6 +10,13 @@
 #include <sys/types.h>
 #include <map>
 
+#include "src/base64.h"
+#include "src/globals.h"
+#include "src/logging.h"
+#include "src/object.h"
+#include "src/scoped_ptr.h"
+#include "src/utils.h"
+
 namespace art {
 
 const byte RawDexFile::kDexMagic[] = { 'd', 'e', 'x', '\n' };
@@ -162,4 +165,126 @@
   }
 }
 
+// Read a signed integer.  "zwidth" is the zero-based byte count.
+static int32_t ReadSignedInt(const byte* ptr, int zwidth)
+{
+  int32_t val = 0;
+  for (int i = zwidth; i >= 0; --i) {
+    val = ((uint32_t)val >> 8) | (((int32_t)*ptr++) << 24);
+  }
+  val >>= (3 - zwidth) * 8;
+  return val;
+}
+
+// Read an unsigned integer.  "zwidth" is the zero-based byte count,
+// "fill_on_right" indicates which side we want to zero-fill from.
+static uint32_t ReadUnsignedInt(const byte* ptr, int zwidth,
+                                bool fill_on_right) {
+  uint32_t val = 0;
+  if (!fill_on_right) {
+    for (int i = zwidth; i >= 0; --i) {
+      val = (val >> 8) | (((uint32_t)*ptr++) << 24);
+    }
+    val >>= (3 - zwidth) * 8;
+  } else {
+    for (int i = zwidth; i >= 0; --i) {
+      val = (val >> 8) | (((uint32_t)*ptr++) << 24);
+    }
+  }
+  return val;
+}
+
+// Read a signed long.  "zwidth" is the zero-based byte count.
+static int64_t ReadSignedLong(const byte* ptr, int zwidth) {
+  int64_t val = 0;
+  for (int i = zwidth; i >= 0; --i) {
+    val = ((uint64_t)val >> 8) | (((int64_t)*ptr++) << 56);
+  }
+  val >>= (7 - zwidth) * 8;
+  return val;
+}
+
+// Read an unsigned long.  "zwidth" is the zero-based byte count,
+// "fill_on_right" indicates which side we want to zero-fill from.
+static uint64_t ReadUnsignedLong(const byte* ptr, int zwidth,
+                                 bool fill_on_right) {
+  uint64_t val = 0;
+  if (!fill_on_right) {
+    for (int i = zwidth; i >= 0; --i) {
+      val = (val >> 8) | (((uint64_t)*ptr++) << 56);
+    }
+    val >>= (7 - zwidth) * 8;
+  } else {
+    for (int i = zwidth; i >= 0; --i) {
+      val = (val >> 8) | (((uint64_t)*ptr++) << 56);
+    }
+  }
+  return val;
+}
+
+RawDexFile::ValueType RawDexFile::ReadEncodedValue(const byte** stream,
+                                                   JValue* value) {
+  const byte* ptr = *stream;
+  byte value_type = *ptr++;
+  byte value_arg = value_type >> kEncodedValueArgShift;
+  size_t width = value_arg + 1;  // assume and correct later
+  int type = value_type & kEncodedValueTypeMask;
+  switch (type) {
+    case RawDexFile::kByte: {
+      int32_t b = ReadSignedInt(ptr, value_arg);
+      CHECK(IsInt(8, b));
+      value->i = b;
+      break;
+    }
+    case RawDexFile::kShort: {
+      int32_t s = ReadSignedInt(ptr, value_arg);
+      CHECK(IsInt(16, s));
+      value->i = s;
+      break;
+    }
+    case RawDexFile::kChar: {
+      uint32_t c = ReadUnsignedInt(ptr, value_arg, false);
+      CHECK(IsUint(16, c));
+      value->i = c;
+      break;
+    }
+    case RawDexFile::kInt:
+      value->i = ReadSignedInt(ptr, value_arg);
+      break;
+    case RawDexFile::kLong:
+      value->j = ReadSignedLong(ptr, value_arg);
+      break;
+    case RawDexFile::kFloat:
+      value->i = ReadUnsignedInt(ptr, value_arg, true);
+      break;
+    case RawDexFile::kDouble:
+      value->j = ReadUnsignedLong(ptr, value_arg, true);
+      break;
+    case RawDexFile::kBoolean:
+      value->i = (value_arg != 0);
+      width = 0;
+      break;
+    case RawDexFile::kString:
+    case RawDexFile::kType:
+    case RawDexFile::kMethod:
+    case RawDexFile::kEnum:
+      value->i = ReadUnsignedInt(ptr, value_arg, false);
+      break;
+    case RawDexFile::kField:
+    case RawDexFile::kArray:
+    case RawDexFile::kAnnotation:
+      LOG(FATAL) << "Unimplemented";
+      break;
+    case RawDexFile::kNull:
+      value->i = 0;
+      width = 0;
+      break;
+    default:
+      LOG(FATAL) << "Unreached";
+  }
+  ptr += width;
+  *stream = ptr;
+  return static_cast<ValueType>(type);
+}
+
 }  // namespace art
diff --git a/src/raw_dex_file.h b/src/raw_dex_file.h
index 56b6ff6..afd65c2 100644
--- a/src/raw_dex_file.h
+++ b/src/raw_dex_file.h
@@ -13,15 +13,40 @@
 
 namespace art {
 
+union JValue;
+
+// TODO: move all of the macro functionality into the DexFile class.
 class RawDexFile {
  public:
   static const byte kDexMagic[];
   static const byte kDexMagicVersion[];
   static const size_t kSha1DigestSize = 20;
 
+  static const byte kEncodedValueTypeMask = 0x1f;  // 0b11111
+  static const byte kEncodedValueArgShift = 5;
+
   // The value of an invalid index.
   static const uint32_t kDexNoIndex = 0xFFFFFFFF;
 
+  enum ValueType {
+    kByte = 0x00,
+    kShort = 0x02,
+    kChar = 0x03,
+    kInt = 0x04,
+    kLong = 0x06,
+    kFloat = 0x10,
+    kDouble = 0x11,
+    kString = 0x17,
+    kType = 0x18,
+    kField = 0x19,
+    kMethod = 0x1a,
+    kEnum = 0x1b,
+    kArray = 0x1c,
+    kAnnotation = 0x1d,
+    kNull = 0x1e,
+    kBoolean = 0x1f
+  };
+
   // Raw header_item.
   struct Header {
     uint8_t magic_[8];
@@ -114,7 +139,7 @@
     TypeItem list_[1];  // elements of the list
   };
 
-  class ParameterIterator {
+  class ParameterIterator {  // TODO: stream
    public:
     ParameterIterator(const RawDexFile& raw, const ProtoId& proto_id)
         : raw_(raw), size_(0), pos_(0) {
@@ -146,7 +171,7 @@
   }
 
   // Raw code_item.
-  struct Code {
+  struct CodeItem {
     uint16_t registers_size_;
     uint16_t ins_size_;
     uint16_t outs_size_;
@@ -310,12 +335,12 @@
     }
   }
 
-  const Code* GetCode(const Method& method) const {
+  const CodeItem* GetCodeItem(const Method& method) const {
     if (method.code_off_ == 0) {
       return NULL;  // native or abstract method
     } else {
       const byte* addr = base_ + method.code_off_;
-      return reinterpret_cast<const Code*>(addr);
+      return reinterpret_cast<const CodeItem*>(addr);
     }
   }
 
@@ -334,11 +359,26 @@
     }
   }
 
+  const byte* GetEncodedArray(const ClassDef& class_def) const {
+    if (class_def.static_values_off_ == 0) {
+      return 0;
+    } else {
+      return base_ + class_def.static_values_off_;
+    }
+  }
+
+  int32_t GetStringLength(const StringId& string_id) const {
+    const byte* ptr = base_ + string_id.string_data_off_;
+    return DecodeUnsignedLeb128(&ptr);
+  }
+
+  ValueType ReadEncodedValue(const byte** encoded_value, JValue* value);
+
   // From libdex...
 
   // Returns a pointer to the UTF-8 string data referred to by the
   // given string_id.
-  const char* dexGetStringData(const StringId& string_id) const {
+  const char* GetStringData(const StringId& string_id) const {
     const byte* ptr = base_ + string_id.string_data_off_;
     // Skip the uleb128 length.
     while (*(ptr++) > 0x7f) /* empty */ ;
@@ -348,7 +388,7 @@
   // return the UTF-8 encoded string with the specified string_id index
   const char* dexStringById(uint32_t idx) const {
     const StringId& string_id = GetStringId(idx);
-    return dexGetStringData(string_id);
+    return GetStringData(string_id);
   }
 
   // Get the descriptor string associated with a given type index.