Complete support for loading classes from a DEX file.

Change-Id: I1b9aa105fc78df170e83b259d8d04317c296a1b5
diff --git a/src/dex_file.cc b/src/dex_file.cc
index a89baaf..1951af5 100644
--- a/src/dex_file.cc
+++ b/src/dex_file.cc
@@ -52,8 +52,7 @@
 
 Class* DexFile::LoadClass(const RawDexFile::ClassDef& class_def) {
   const byte* class_data = raw_->GetClassData(class_def);
-  RawDexFile::ClassDataHeader header;
-  raw_->DecodeClassDataHeader(&header, class_data);
+  RawDexFile::ClassDataHeader header = raw_->ReadClassDataHeader(&class_data);
 
   const char* descriptor = raw_->GetClassDescriptor(class_def);
   CHECK(descriptor != NULL);
@@ -61,9 +60,9 @@
   // Allocate storage for the new class object.
   size_t size = Class::Size(header.static_fields_size_);
   Class* klass = Heap::AllocClass(size);
-  CHECK(klass != NULL);
+  CHECK(klass != NULL);  // TODO: throw an OOME
 
-  //klass->klass_ = NULL;  // TODO
+  klass->klass_ = NULL;  // TODO
   klass->descriptor_ = descriptor;
   klass->access_flags_ = class_def.access_flags_;
   klass->class_loader_ = NULL;  // TODO
@@ -73,32 +72,70 @@
 
   klass->super_ = reinterpret_cast<Class*>(class_def.superclass_idx_);
 
+  klass->num_sfields_ = header.static_fields_size_;
+  klass->num_ifields_ = header.instance_fields_size_;
+  klass->num_dmethods_ = header.direct_methods_size_;
+  klass->num_vmethods_ = header.virtual_methods_size_;
+
+  klass->source_file_ = raw_->dexGetSourceFile(class_def);
+
   // Load class interfaces.
-  LoadClassInterfaces(class_def, klass);
+  LoadInterfaces(class_def, klass);
 
   // Load static fields.
-  if (header.static_fields_size_ != 0) {
-    for (size_t i = 0; i < header.static_fields_size_; ++i) {
-      // TODO
+  if (klass->num_sfields_ != 0) {
+    uint32_t last_idx = 0;
+    for (size_t i = 0; i < klass->num_sfields_; ++i) {
+      RawDexFile::Field raw_field;
+      raw_->dexReadClassDataField(&class_data, &raw_field, &last_idx);
+      LoadField(klass, raw_field, &klass->sfields_[i]);
     }
   }
 
   // Load instance fields.
-  if (header.instance_fields_size_ != 0) {
-    for (size_t i = 0; i < header.instance_fields_size_; ++i) {
-      // TODO
+  if (klass->num_ifields_ != 0) {
+    // TODO: append instance fields to class object
+    klass->ifields_ = new IField[klass->num_ifields_];
+    uint32_t last_idx = 0;
+    for (size_t i = 0; i < klass->num_ifields_; ++i) {
+      RawDexFile::Field raw_field;
+      raw_->dexReadClassDataField(&class_data, &raw_field, &last_idx);
+      LoadField(klass, raw_field, &klass->ifields_[i]);
     }
   }
 
   // Load direct methods.
+  if (klass->num_dmethods_ != 0) {
+    // TODO: append direct methods to class object
+    klass->dmethods_ = new Method[klass->num_dmethods_];
+    uint32_t last_idx = 0;
+    for (size_t i = 0; i < klass->num_dmethods_; ++i) {
+      RawDexFile::Method raw_method;
+      raw_->dexReadClassDataMethod(&class_data, &raw_method, &last_idx);
+      LoadMethod(klass, raw_method, &klass->dmethods_[i]);
+      // TODO: register maps
+    }
+  }
 
   // Load virtual methods.
+  if (klass->num_vmethods_ != 0) {
+    // TODO: append virtual methods to class object
+    klass->vmethods_ = new Method[klass->num_vmethods_];
+    memset(klass->vmethods_, 0xff, sizeof(Method));
+    uint32_t last_idx = 0;
+    for (size_t i = 0; i < klass->num_vmethods_; ++i) {
+      RawDexFile::Method raw_method;
+      raw_->dexReadClassDataMethod(&class_data, &raw_method, &last_idx);
+      LoadMethod(klass, raw_method, &klass->vmethods_[i]);
+      // TODO: register maps
+    }
+  }
 
   return klass;
 }
 
-void DexFile::LoadClassInterfaces(const RawDexFile::ClassDef& class_def,
-                                  Class* klass) {
+void DexFile::LoadInterfaces(const RawDexFile::ClassDef& class_def,
+                             Class* klass) {
   const RawDexFile::TypeList* list = raw_->GetInterfacesList(class_def);
   if (list != NULL) {
     klass->interface_count_ = list->Size();
@@ -110,19 +147,41 @@
   }
 }
 
-void DexFile::LoadSFields(Class* klass, const RawDexFile::Field* src,
-                            Field* dst) {
-
+void DexFile::LoadField(Class* klass, const RawDexFile::Field& src,
+                        Field* dst) {
+  const RawDexFile::FieldId& field_id = raw_->GetFieldId(src.field_idx_);
+  dst->klass_ = klass;
+  dst->name_ = raw_->dexStringById(field_id.name_idx_);
+  dst->signature_ = raw_->dexStringByTypeIdx(field_id.type_idx_);
+  dst->access_flags_ = src.access_flags_;
 }
 
-void DexFile::LoadIFields(Class* klass, const RawDexFile::Field* src,
-                          Field* dst) {
-}
-
-void DexFile::LoadMethod(Class* klass, const RawDexFile::Method* src,
+void DexFile::LoadMethod(Class* klass, const RawDexFile::Method& src,
                          Method* dst) {
+  const RawDexFile::MethodId& method_id = raw_->GetMethodId(src.method_idx_);
+  dst->klass_ = klass;
+  dst->name_ = raw_->dexStringById(method_id.name_idx_);
+  dst->dex_file_ = this;
+  dst->proto_idx_ = method_id.proto_idx_;
+  dst->shorty_ = raw_->GetShorty(method_id.proto_idx_);
+  dst->access_flags_ = src.access_flags_;
+
+  // TODO: check for finalize method
+
+  const RawDexFile::Code* code_item = raw_->GetCode(src);
+  if (code_item != NULL) {
+    dst->num_registers_ = code_item->registers_size_;
+    dst->num_ins_ = code_item->ins_size_;
+    dst->num_outs_ = code_item->outs_size_;
+    dst->insns_ = code_item->insns_;
+  } else {
+    uint16_t num_args = dst->NumArgRegisters();
+    if (!dst->IsStatic()) {
+      ++num_args;
+    }
+    dst->num_registers_ = dst->num_ins_ + num_args;
+    // TODO: native methods
+  }
 }
 
-
-
 }  // namespace art