Refactor the use of Method by the compiler.

Remove the dependence on the Method object in dex2oat, allowing lazier
resolution.
Introduce new find and iterators in DexFile to simplify common
operations and avoid misuse of class data items.

Change-Id: I39fb8252190f543d89d8b233076355cec310fe08
diff --git a/build/Android.common.mk b/build/Android.common.mk
index 968228b..4b0cdfe 100644
--- a/build/Android.common.mk
+++ b/build/Android.common.mk
@@ -247,7 +247,7 @@
 TEST_DEX_DIRECTORIES := \
 	AbstractMethod \
 	AllFields \
-	CreateMethodDescriptor \
+	CreateMethodSignature \
 	ExceptionHandle \
 	ExceptionTest \
 	Fibonacci \
diff --git a/src/calling_convention.h b/src/calling_convention.h
index 3a7cf1e..7e87264 100644
--- a/src/calling_convention.h
+++ b/src/calling_convention.h
@@ -124,8 +124,6 @@
   // always at the bottom of a frame, but this doesn't work for outgoing
   // native args). Includes alignment.
   virtual size_t FrameSize() = 0;
-  // Offset within the frame of the return pc
-  virtual size_t ReturnPcOffset() = 0;
   // Size of outgoing arguments, including alignment
   virtual size_t OutArgSize() = 0;
   // Number of references in stack indirect reference table
diff --git a/src/calling_convention_arm.cc b/src/calling_convention_arm.cc
index 89d4170..fc8c662 100644
--- a/src/calling_convention_arm.cc
+++ b/src/calling_convention_arm.cc
@@ -146,11 +146,6 @@
                  kStackAlignment);
 }
 
-size_t ArmJniCallingConvention::ReturnPcOffset() {
-  // Link register is always the first value pushed when the frame is constructed
-  return FrameSize() - kPointerSize;
-}
-
 // Will reg be crushed by an outgoing argument?
 bool ArmJniCallingConvention::IsMethodRegisterClobberedPreCall() {
   return true;  // The method register R0 is always clobbered by the JNIEnv
diff --git a/src/calling_convention_arm.h b/src/calling_convention_arm.h
index 2a056a8..4ecf9df 100644
--- a/src/calling_convention_arm.h
+++ b/src/calling_convention_arm.h
@@ -37,7 +37,6 @@
   // JNI calling convention
   virtual void Next();  // Override default behavior for AAPCS
   virtual size_t FrameSize();
-  virtual size_t ReturnPcOffset();
   virtual size_t OutArgSize();
   virtual const std::vector<ManagedRegister>& CalleeSaveRegisters() const {
     return callee_save_regs_;
diff --git a/src/calling_convention_x86.cc b/src/calling_convention_x86.cc
index da76e17..07ccece 100644
--- a/src/calling_convention_x86.cc
+++ b/src/calling_convention_x86.cc
@@ -84,11 +84,6 @@
   return RoundUp(NumberOfOutgoingStackArgs() * kPointerSize, kStackAlignment);
 }
 
-size_t X86JniCallingConvention::ReturnPcOffset() {
-  // Return PC is pushed at the top of the frame by the call into the method
-  return FrameSize() - kPointerSize;
-}
-
 bool X86JniCallingConvention::IsMethodRegisterClobberedPreCall() {
   return GetMethod()->IsSynchronized();  // Monitor enter crushes the method register
 }
diff --git a/src/calling_convention_x86.h b/src/calling_convention_x86.h
index b796ba0..f3c85e9 100644
--- a/src/calling_convention_x86.h
+++ b/src/calling_convention_x86.h
@@ -37,7 +37,6 @@
   virtual ManagedRegister InterproceduralScratchRegister();
   // JNI calling convention
   virtual size_t FrameSize();
-  virtual size_t ReturnPcOffset();
   virtual size_t OutArgSize();
   virtual const std::vector<ManagedRegister>& CalleeSaveRegisters() const {
     DCHECK(callee_save_regs_.empty());
diff --git a/src/class_linker.cc b/src/class_linker.cc
index 4f387db..584c53e 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -14,6 +14,7 @@
 #include "dex_verifier.h"
 #include "heap.h"
 #include "intern_table.h"
+#include "leb128.h"
 #include "logging.h"
 #include "monitor.h"
 #include "oat_file.h"
@@ -1070,17 +1071,12 @@
 size_t ClassLinker::SizeOfClass(const DexFile& dex_file,
                                 const DexFile::ClassDef& dex_class_def) {
   const byte* class_data = dex_file.GetClassData(dex_class_def);
-  DexFile::ClassDataHeader header = dex_file.ReadClassDataHeader(&class_data);
-  size_t num_static_fields = header.static_fields_size_;
   size_t num_ref = 0;
   size_t num_32 = 0;
   size_t num_64 = 0;
-  if (num_static_fields != 0) {
-    uint32_t last_idx = 0;
-    for (size_t i = 0; i < num_static_fields; ++i) {
-      DexFile::Field dex_field;
-      dex_file.dexReadClassDataField(&class_data, &dex_field, &last_idx);
-      const DexFile::FieldId& field_id = dex_file.GetFieldId(dex_field.field_idx_);
+  if (class_data != NULL) {
+    for (ClassDataItemIterator it(dex_file, class_data); it.HasNextStaticField(); it.Next()) {
+      const DexFile::FieldId& field_id = dex_file.GetFieldId(it.GetMemberIndex());
       const char* descriptor = dex_file.GetFieldTypeDescriptor(field_id);
       char c = descriptor[0];
       if (c == 'L' || c == '[') {
@@ -1092,7 +1088,6 @@
       }
     }
   }
-
   // start with generic class data
   size_t size = sizeof(Class);
   // follow with reference fields which must be contiguous at start
@@ -1137,9 +1132,6 @@
   CHECK(klass.get() != NULL);
   CHECK(klass->GetDexCache() != NULL);
   CHECK_EQ(Class::kStatusNotReady, klass->GetStatus());
-  const byte* class_data = dex_file.GetClassData(dex_class_def);
-  DexFile::ClassDataHeader header = dex_file.ReadClassDataHeader(&class_data);
-
   const char* descriptor = dex_file.GetClassDescriptor(dex_class_def);
   CHECK(descriptor != NULL);
 
@@ -1164,12 +1156,7 @@
   klass->SetSuperClassTypeIdx(dex_class_def.superclass_idx_);
   klass->SetAnnotationsOffset(dex_class_def.annotations_off_);
 
-  size_t num_static_fields = header.static_fields_size_;
-  size_t num_instance_fields = header.instance_fields_size_;
-  size_t num_direct_methods = header.direct_methods_size_;
-  size_t num_virtual_methods = header.virtual_methods_size_;
-
-  const char* source_file = dex_file.dexGetSourceFile(dex_class_def);
+  const char* source_file = dex_file.GetSourceFile(dex_class_def);
   if (source_file != NULL) {
     String* source_file_string = intern_table_->InternStrong(source_file);
     if (source_file_string == NULL) {
@@ -1181,30 +1168,27 @@
   // Load class interfaces.
   LoadInterfaces(dex_file, dex_class_def, klass);
 
-  // Load static fields.
-  if (num_static_fields != 0) {
-    klass->SetSFields(AllocObjectArray<Field>(num_static_fields));
-    uint32_t last_idx = 0;
-    for (size_t i = 0; i < num_static_fields; ++i) {
-      DexFile::Field dex_field;
-      dex_file.dexReadClassDataField(&class_data, &dex_field, &last_idx);
-      SirtRef<Field> sfield(AllocField());
-      klass->SetStaticField(i, sfield.get());
-      LoadField(dex_file, dex_field, klass, sfield);
-    }
+  // Load fields fields.
+  const byte* class_data = dex_file.GetClassData(dex_class_def);
+  if (class_data == NULL) {
+    return;  // no fields or methods - for example a marker interface
   }
-
-  // Load instance fields.
-  if (num_instance_fields != 0) {
-    klass->SetIFields(AllocObjectArray<Field>(num_instance_fields));
-    uint32_t last_idx = 0;
-    for (size_t i = 0; i < num_instance_fields; ++i) {
-      DexFile::Field dex_field;
-      dex_file.dexReadClassDataField(&class_data, &dex_field, &last_idx);
-      SirtRef<Field> ifield(AllocField());
-      klass->SetInstanceField(i, ifield.get());
-      LoadField(dex_file, dex_field, klass, ifield);
-    }
+  ClassDataItemIterator it(dex_file, class_data);
+  if (it.NumStaticFields() != 0) {
+    klass->SetSFields(AllocObjectArray<Field>(it.NumStaticFields()));
+  }
+  if (it.NumInstanceFields() != 0) {
+    klass->SetIFields(AllocObjectArray<Field>(it.NumInstanceFields()));
+  }
+  for (size_t i = 0; it.HasNextStaticField(); i++, it.Next()) {
+    SirtRef<Field> sfield(AllocField());
+    klass->SetStaticField(i, sfield.get());
+    LoadField(dex_file, it, klass, sfield);
+  }
+  for (size_t i = 0; it.HasNextInstanceField(); i++, it.Next()) {
+    SirtRef<Field> ifield(AllocField());
+    klass->SetInstanceField(i, ifield.get());
+    LoadField(dex_file, it, klass, ifield);
   }
 
   UniquePtr<const OatFile::OatClass> oat_class;
@@ -1221,41 +1205,35 @@
       }
     }
   }
-  size_t method_index = 0;
-
-  // Load direct methods.
-  if (num_direct_methods != 0) {
+  // Load methods.
+  if (it.NumDirectMethods() != 0) {
     // TODO: append direct methods to class object
-    klass->SetDirectMethods(AllocObjectArray<Method>(num_direct_methods));
-    uint32_t last_idx = 0;
-    for (size_t i = 0; i < num_direct_methods; ++i, ++method_index) {
-      DexFile::Method dex_method;
-      dex_file.dexReadClassDataMethod(&class_data, &dex_method, &last_idx);
-      SirtRef<Method> method(AllocMethod());
-      klass->SetDirectMethod(i, method.get());
-      LoadMethod(dex_file, dex_method, klass, method);
-      if (oat_class.get() != NULL) {
-        LinkCode(method, oat_class.get(), method_index);
-      }
-    }
+    klass->SetDirectMethods(AllocObjectArray<Method>(it.NumDirectMethods()));
   }
-
-  // Load virtual methods.
-  if (num_virtual_methods != 0) {
-    // TODO: append virtual methods to class object
-    klass->SetVirtualMethods(AllocObjectArray<Method>(num_virtual_methods));
-    uint32_t last_idx = 0;
-    for (size_t i = 0; i < num_virtual_methods; ++i, ++method_index) {
-      DexFile::Method dex_method;
-      dex_file.dexReadClassDataMethod(&class_data, &dex_method, &last_idx);
-      SirtRef<Method> method(AllocMethod());
-      klass->SetVirtualMethod(i, method.get());
-      LoadMethod(dex_file, dex_method, klass, method);
-      if (oat_class.get() != NULL) {
-        LinkCode(method, oat_class.get(), method_index);
-      }
-    }
+  if (it.NumVirtualMethods() != 0) {
+    // TODO: append direct methods to class object
+    klass->SetVirtualMethods(AllocObjectArray<Method>(it.NumVirtualMethods()));
   }
+  size_t method_index = 0;
+  for (size_t i = 0; it.HasNextDirectMethod(); i++, it.Next()) {
+    SirtRef<Method> method(AllocMethod());
+    klass->SetDirectMethod(i, method.get());
+    LoadMethod(dex_file, it, klass, method);
+    if (oat_class.get() != NULL) {
+      LinkCode(method, oat_class.get(), method_index);
+    }
+    method_index++;
+  }
+  for (size_t i = 0; it.HasNextVirtualMethod(); i++, it.Next()) {
+    SirtRef<Method> method(AllocMethod());
+    klass->SetVirtualMethod(i, method.get());
+    LoadMethod(dex_file, it, klass, method);
+    if (oat_class.get() != NULL) {
+      LinkCode(method, oat_class.get(), method_index);
+    }
+    method_index++;
+  }
+  DCHECK(!it.HasNext());
 }
 
 void ClassLinker::LoadInterfaces(const DexFile& dex_file,
@@ -1273,15 +1251,13 @@
   }
 }
 
-void ClassLinker::LoadField(const DexFile& dex_file,
-                            const DexFile::Field& src,
-                            SirtRef<Class>& klass,
-                            SirtRef<Field>& dst) {
-  const DexFile::FieldId& field_id = dex_file.GetFieldId(src.field_idx_);
+void ClassLinker::LoadField(const DexFile& dex_file, const ClassDataItemIterator& it,
+                            SirtRef<Class>& klass, SirtRef<Field>& dst) {
+  const DexFile::FieldId& field_id = dex_file.GetFieldId(it.GetMemberIndex());
   dst->SetDeclaringClass(klass.get());
   dst->SetName(ResolveString(dex_file, field_id.name_idx_, klass->GetDexCache()));
   dst->SetTypeIdx(field_id.type_idx_);
-  dst->SetAccessFlags(src.access_flags_);
+  dst->SetAccessFlags(it.GetMemberAccessFlags());
 
   // In order to access primitive types using GetTypeDuringLinking we need to
   // ensure they are resolved into the dex cache
@@ -1293,11 +1269,9 @@
   }
 }
 
-void ClassLinker::LoadMethod(const DexFile& dex_file,
-                             const DexFile::Method& src,
-                             SirtRef<Class>& klass,
-                             SirtRef<Method>& dst) {
-  const DexFile::MethodId& method_id = dex_file.GetMethodId(src.method_idx_);
+void ClassLinker::LoadMethod(const DexFile& dex_file, const ClassDataItemIterator& it,
+                             SirtRef<Class>& klass, SirtRef<Method>& dst) {
+  const DexFile::MethodId& method_id = dex_file.GetMethodId(it.GetMemberIndex());
   dst->SetDeclaringClass(klass.get());
 
   String* method_name = ResolveString(dex_file, method_id.name_idx_, klass->GetDexCache());
@@ -1310,7 +1284,7 @@
   }
 
   int32_t utf16_length;
-  std::string signature(dex_file.CreateMethodDescriptor(method_id.proto_idx_, &utf16_length));
+  std::string signature(dex_file.CreateMethodSignature(method_id.proto_idx_, &utf16_length));
   String* signature_string = intern_table_->InternStrong(utf16_length, signature.c_str());
   if (signature_string == NULL) {
     return;
@@ -1333,14 +1307,14 @@
   }
 
   dst->SetProtoIdx(method_id.proto_idx_);
-  dst->SetCodeItemOffset(src.code_off_);
+  dst->SetCodeItemOffset(it.GetMethodCodeItemOffset());
   const char* shorty = dex_file.GetShorty(method_id.proto_idx_);
   String* shorty_string = intern_table_->InternStrong(shorty);
   dst->SetShorty(shorty_string);
   if (shorty_string == NULL) {
     return;
   }
-  dst->SetAccessFlags(src.access_flags_);
+  dst->SetAccessFlags(it.GetMemberAccessFlags());
   uint32_t return_type_idx = dex_file.GetProtoId(method_id.proto_idx_).return_type_idx_;
   DCHECK_LT(return_type_idx, dex_file.NumTypeIds());
   dst->SetReturnTypeIdx(return_type_idx);
@@ -1354,14 +1328,14 @@
 
   // TODO: check for finalize method
 
-  const DexFile::CodeItem* code_item = dex_file.GetCodeItem(src);
+  const DexFile::CodeItem* code_item = it.GetMethodCodeItem();
   if (code_item != NULL) {
     dst->SetNumRegisters(code_item->registers_size_);
     dst->SetNumIns(code_item->ins_size_);
     dst->SetNumOuts(code_item->outs_size_);
   } else {
     uint16_t num_args = Method::NumArgRegisters(shorty);
-    if ((src.access_flags_ & kAccStatic) != 0) {
+    if ((it.GetMemberAccessFlags() & kAccStatic) != 0) {
       ++num_args;
     }
     dst->SetNumRegisters(num_args);
@@ -1944,9 +1918,8 @@
   }
   const DexFile& dex_file = FindDexFile(method->GetDeclaringClass()->GetDexCache());
   const DexFile::ProtoId& proto_id = dex_file.GetProtoId(method->GetProtoIdx());
-  DexFile::ParameterIterator *it;
-  for (it = dex_file.GetParameterIterator(proto_id); it->HasNext(); it->Next()) {
-    const char* descriptor = it->GetDescriptor();
+  for (DexFileParameterIterator it(dex_file, proto_id); it.HasNext(); it.Next()) {
+    const char* descriptor = it.GetDescriptor();
     if (descriptor == NULL) {
       break;
     }
@@ -2031,15 +2004,12 @@
 }
 
 void ClassLinker::ConstructFieldMap(const DexFile& dex_file, const DexFile::ClassDef& dex_class_def,
-    Class* c, std::map<int, Field*>& field_map) {
+                                    Class* c, std::map<uint32_t, Field*>& field_map) {
   const ClassLoader* cl = c->GetClassLoader();
   const byte* class_data = dex_file.GetClassData(dex_class_def);
-  DexFile::ClassDataHeader header = dex_file.ReadClassDataHeader(&class_data);
-  uint32_t last_idx = 0;
-  for (size_t i = 0; i < header.static_fields_size_; ++i) {
-    DexFile::Field dex_field;
-    dex_file.dexReadClassDataField(&class_data, &dex_field, &last_idx);
-    field_map[i] = ResolveField(dex_file, dex_field.field_idx_, c->GetDexCache(), cl, true);
+  ClassDataItemIterator it(dex_file, class_data);
+  for (size_t i = 0; it.HasNextStaticField(); i++, it.Next()) {
+    field_map[i] = ResolveField(dex_file, it.GetMemberIndex(), c->GetDexCache(), cl, true);
   }
 }
 
@@ -2053,61 +2023,18 @@
   if (dex_cache == NULL) {
     return;
   }
-  const std::string descriptor(klass->GetDescriptor()->ToModifiedUtf8());
   const DexFile& dex_file = FindDexFile(dex_cache);
+  const std::string descriptor(klass->GetDescriptor()->ToModifiedUtf8());
   const DexFile::ClassDef* dex_class_def = dex_file.FindClassDef(descriptor);
   CHECK(dex_class_def != NULL);
+  EncodedStaticFieldValueIterator it(dex_file, dex_cache, this, *dex_class_def);
 
-  // We reordered the fields, so we need to be able to map the field indexes to the right fields.
-  std::map<int, Field*> field_map;
-  ConstructFieldMap(dex_file, *dex_class_def, klass, field_map);
-
-  const byte* addr = dex_file.GetEncodedArray(*dex_class_def);
-  if (addr == NULL) {
-    // All this class' static fields have default values.
-    return;
-  }
-  size_t array_size = DecodeUnsignedLeb128(&addr);
-  for (size_t i = 0; i < array_size; ++i) {
-    Field* field = field_map[i];
-    JValue value;
-    DexFile::ValueType type = dex_file.ReadEncodedValue(&addr, &value);
-    switch (type) {
-      case DexFile::kByte:
-        field->SetByte(NULL, value.b);
-        break;
-      case DexFile::kShort:
-        field->SetShort(NULL, value.s);
-        break;
-      case DexFile::kChar:
-        field->SetChar(NULL, value.c);
-        break;
-      case DexFile::kInt:
-        field->SetInt(NULL, value.i);
-        break;
-      case DexFile::kLong:
-        field->SetLong(NULL, value.j);
-        break;
-      case DexFile::kFloat:
-        field->SetFloat(NULL, value.f);
-        break;
-      case DexFile::kDouble:
-        field->SetDouble(NULL, value.d);
-        break;
-      case DexFile::kString: {
-        uint32_t string_idx = value.i;
-        const String* resolved = ResolveString(dex_file, string_idx, klass->GetDexCache());
-        field->SetObject(NULL, resolved);
-        break;
-      }
-      case DexFile::kBoolean:
-        field->SetBoolean(NULL, value.z);
-        break;
-      case DexFile::kNull:
-        field->SetObject(NULL, value.l);
-        break;
-      default:
-        LOG(FATAL) << "Unknown type " << static_cast<int>(type);
+  if (it.HasNext()) {
+    // We reordered the fields, so we need to be able to map the field indexes to the right fields.
+    std::map<uint32_t, Field*> field_map;
+    ConstructFieldMap(dex_file, *dex_class_def, klass, field_map);
+    for (size_t i = 0; it.HasNext(); i++, it.Next()) {
+      it.ReadValueToField(field_map[i]);
     }
   }
 }
@@ -2135,7 +2062,7 @@
 
 bool ClassLinker::LoadSuperAndInterfaces(SirtRef<Class>& klass, const DexFile& dex_file) {
   CHECK_EQ(Class::kStatusIdx, klass->GetStatus());
-  if (klass->GetSuperClassTypeIdx() != DexFile::kDexNoIndex) {
+  if (klass->GetSuperClassTypeIdx() != DexFile::kDexNoIndex16) {
     Class* super_class = ResolveType(dex_file, klass->GetSuperClassTypeIdx(), klass.get());
     if (super_class == NULL) {
       DCHECK(Thread::Current()->IsExceptionPending());
@@ -2691,7 +2618,7 @@
                                 const ClassLoader* class_loader) {
   Class* resolved = dex_cache->GetResolvedType(type_idx);
   if (resolved == NULL) {
-    const char* descriptor = dex_file.dexStringByTypeIdx(type_idx);
+    const char* descriptor = dex_file.StringByTypeIdx(type_idx);
     resolved = FindClass(descriptor, class_loader);
     if (resolved != NULL) {
       Class* check = resolved;
@@ -2731,8 +2658,8 @@
     return NULL;
   }
 
-  const char* name = dex_file.dexStringById(method_id.name_idx_);
-  std::string signature(dex_file.CreateMethodDescriptor(method_id.proto_idx_, NULL));
+  const char* name = dex_file.StringDataByIdx(method_id.name_idx_);
+  std::string signature(dex_file.CreateMethodSignature(method_id.proto_idx_, NULL));
   if (is_direct) {
     resolved = klass->FindDirectMethod(name, signature);
   } else if (klass->IsInterface()) {
diff --git a/src/class_linker.h b/src/class_linker.h
index 03c8341..478a260 100644
--- a/src/class_linker.h
+++ b/src/class_linker.h
@@ -282,7 +282,7 @@
   void AppendToBootClassPath(const DexFile& dex_file, SirtRef<DexCache>& dex_cache);
 
   void ConstructFieldMap(const DexFile& dex_file, const DexFile::ClassDef& dex_class_def,
-      Class* c, std::map<int, Field*>& field_map);
+                         Class* c, std::map<uint32_t, Field*>& field_map);
 
   size_t SizeOfClass(const DexFile& dex_file,
                      const DexFile::ClassDef& dex_class_def);
@@ -296,15 +296,11 @@
                       const DexFile::ClassDef& dex_class_def,
                       SirtRef<Class>& klass);
 
-  void LoadField(const DexFile& dex_file,
-                 const DexFile::Field& dex_field,
-                 SirtRef<Class>& klass,
+  void LoadField(const DexFile& dex_file, const ClassDataItemIterator& it, SirtRef<Class>& klass,
                  SirtRef<Field>& dst);
 
-  void LoadMethod(const DexFile& dex_file,
-                  const DexFile::Method& dex_method,
-                  SirtRef<Class>& klass,
-                  SirtRef<Method>& dst);
+  void LoadMethod(const DexFile& dex_file, const ClassDataItemIterator& dex_method,
+                  SirtRef<Class>& klass, SirtRef<Method>& dst);
 
   // Inserts a class into the class table.  Returns true if the class
   // was inserted.
diff --git a/src/common_test.h b/src/common_test.h
index 3966742..56b54a3 100644
--- a/src/common_test.h
+++ b/src/common_test.h
@@ -100,7 +100,9 @@
   void MakeExecutable(Method* method) {
     CHECK(method != NULL);
 
-    const CompiledInvokeStub* compiled_invoke_stub = compiler_->GetCompiledInvokeStub(method);
+    const CompiledInvokeStub* compiled_invoke_stub =
+        compiler_->FindInvokeStub(method->IsStatic(),
+                                  method->GetShorty()->ToModifiedUtf8().c_str());
     CHECK(compiled_invoke_stub != NULL) << PrettyMethod(method);
     const std::vector<uint8_t>& invoke_stub = compiled_invoke_stub->GetCode();
     MakeExecutable(invoke_stub);
@@ -110,7 +112,11 @@
               << " invoke_stub=" << reinterpret_cast<void*>(method_invoke_stub);
 
     if (!method->IsAbstract()) {
-      const CompiledMethod* compiled_method = compiler_->GetCompiledMethod(method);
+      const DexCache* dex_cache = method->GetDeclaringClass()->GetDexCache();
+      const DexFile& dex_file = Runtime::Current()->GetClassLinker()->FindDexFile(dex_cache);
+      const CompiledMethod* compiled_method =
+          compiler_->GetCompiledMethod(Compiler::MethodReference(&dex_file,
+                                                                 method->GetDexMethodIndex()));
       CHECK(compiled_method != NULL) << PrettyMethod(method);
       const std::vector<uint8_t>& code = compiled_method->GetCode();
       MakeExecutable(code);
@@ -119,7 +125,6 @@
       LOG(INFO) << "MakeExecutable " << PrettyMethod(method) << " code=" << method_code;
       OatFile::OatMethod oat_method(method_code,
                                     compiled_method->GetFrameSizeInBytes(),
-                                    compiled_method->GetReturnPcOffsetInBytes(),
                                     compiled_method->GetCoreSpillMask(),
                                     compiled_method->GetFpSpillMask(),
                                     &compiled_method->GetMappingTable()[0],
@@ -134,7 +139,6 @@
                                     kStackAlignment,
                                     0,
                                     0,
-                                    0,
                                     NULL,
                                     NULL,
                                     method_invoke_stub);
diff --git a/src/compiled_method.cc b/src/compiled_method.cc
index 082600f..500a62b 100644
--- a/src/compiled_method.cc
+++ b/src/compiled_method.cc
@@ -7,7 +7,6 @@
 CompiledMethod::CompiledMethod(InstructionSet instruction_set,
                                std::vector<short>& short_code,
                                const size_t frame_size_in_bytes,
-                               const size_t return_pc_offset_in_bytes,
                                const uint32_t core_spill_mask,
                                const uint32_t fp_spill_mask,
                                std::vector<uint32_t>& mapping_table,
@@ -37,7 +36,6 @@
   instruction_set_ = instruction_set;
   code_ = byte_code;
   frame_size_in_bytes_ = frame_size_in_bytes;
-  return_pc_offset_in_bytes_ = return_pc_offset_in_bytes;
   core_spill_mask_ = core_spill_mask;
   fp_spill_mask_ = fp_spill_mask;
   mapping_table_ = length_prefixed_mapping_table;
@@ -49,7 +47,6 @@
 CompiledMethod::CompiledMethod(InstructionSet instruction_set,
                                std::vector<uint8_t>& code,
                                const size_t frame_size_in_bytes,
-                               const size_t return_pc_offset_in_bytes,
                                const uint32_t core_spill_mask,
                                const uint32_t fp_spill_mask) {
   CHECK_NE(code.size(), 0U);
@@ -57,7 +54,6 @@
   instruction_set_ = instruction_set;
   code_ = code;
   frame_size_in_bytes_ = frame_size_in_bytes;
-  return_pc_offset_in_bytes_ = return_pc_offset_in_bytes;
   core_spill_mask_ = core_spill_mask;
   fp_spill_mask_ = fp_spill_mask;
 }
@@ -76,10 +72,6 @@
   return frame_size_in_bytes_;
 }
 
-size_t CompiledMethod::GetReturnPcOffsetInBytes() const {
-  return return_pc_offset_in_bytes_;
-}
-
 uint32_t CompiledMethod::GetCoreSpillMask() const {
   return core_spill_mask_;
 }
@@ -146,7 +138,6 @@
   }
 }
 
-
 CompiledInvokeStub::CompiledInvokeStub(std::vector<uint8_t>& code) {
   CHECK_NE(code.size(), 0U);
   code_ = code;
diff --git a/src/compiled_method.h b/src/compiled_method.h
index 1a5c34d..4e0870b 100644
--- a/src/compiled_method.h
+++ b/src/compiled_method.h
@@ -16,7 +16,6 @@
   CompiledMethod(InstructionSet instruction_set,
                  std::vector<short>& code,
                  const size_t frame_size_in_bytes,
-                 const size_t return_pc_offset_in_bytes,
                  const uint32_t core_spill_mask,
                  const uint32_t fp_spill_mask,
                  std::vector<uint32_t>& mapping_table,
@@ -26,7 +25,6 @@
   CompiledMethod(InstructionSet instruction_set,
                  std::vector<uint8_t>& code,
                  const size_t frame_size_in_bytes,
-                 const size_t return_pc_offset_in_bytes,
                  const uint32_t core_spill_mask,
                  const uint32_t fp_spill_mask);
 
@@ -35,12 +33,10 @@
   InstructionSet GetInstructionSet() const;
   const std::vector<uint8_t>& GetCode() const;
   size_t GetFrameSizeInBytes() const;
-  size_t GetReturnPcOffsetInBytes() const;
   uint32_t GetCoreSpillMask() const;
   uint32_t GetFpSpillMask() const;
   const std::vector<uint32_t>& GetMappingTable() const;
   const std::vector<uint16_t>& GetVmapTable() const;
-
   // Aligns an offset from a page aligned value to make it suitable
   // for code storage. important to ensure that PC relative value
   // computations work out as expected on ARM.
@@ -61,7 +57,6 @@
   InstructionSet instruction_set_;
   std::vector<uint8_t> code_;
   size_t frame_size_in_bytes_;
-  size_t return_pc_offset_in_bytes_;
   uint32_t core_spill_mask_;
   uint32_t fp_spill_mask_;
   std::vector<uint32_t> mapping_table_;
diff --git a/src/compiler.cc b/src/compiler.cc
index ba61b4d..96beaa6 100644
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -14,20 +14,20 @@
 #include "runtime.h"
 #include "stl_util.h"
 
-extern art::CompiledMethod* oatCompileMethod(const art::Compiler& compiler,
-                                             const art::Method*,
-                                             art::InstructionSet);
+art::CompiledMethod* oatCompileMethod(const art::Compiler& compiler, bool is_direct,
+                                      uint32_t method_idx, const art::ClassLoader* class_loader,
+                                      const art::DexFile& dex_file, art::InstructionSet);
 
 namespace art {
 
 namespace arm {
   ByteArray* CreateAbstractMethodErrorStub();
-  CompiledInvokeStub* ArmCreateInvokeStub(const Method* method);
+  CompiledInvokeStub* ArmCreateInvokeStub(bool is_static, const char* shorty);
   ByteArray* ArmCreateResolutionTrampoline(Runtime::TrampolineType type);
 }
 namespace x86 {
   ByteArray* CreateAbstractMethodErrorStub();
-  CompiledInvokeStub* X86CreateInvokeStub(const Method* method);
+  CompiledInvokeStub* X86CreateInvokeStub(bool is_static, const char* shorty);
   ByteArray* X86CreateResolutionTrampoline(Runtime::TrampolineType type);
 }
 
@@ -80,7 +80,12 @@
   Resolve(class_loader);
   Verify(class_loader);
   InitializeClassesWithoutClinit(class_loader);
-  CompileMethod(method);
+  // Find the dex_file
+  const DexCache* dex_cache = method->GetDeclaringClass()->GetDexCache();
+  const DexFile& dex_file = Runtime::Current()->GetClassLinker()->FindDexFile(dex_cache);
+  uint32_t method_idx = method->GetDexMethodIndex();
+  CompileMethod(method->IsDirect(), method->IsNative(), method->IsStatic(), method->IsAbstract(),
+                method_idx, class_loader, dex_file);
   SetCodeAndDirectMethods(class_loader);
 }
 
@@ -127,69 +132,52 @@
     // static fields, instance fields, direct methods, and virtual
     // methods.
     const byte* class_data = dex_file.GetClassData(class_def);
-
-    DexFile::ClassDataHeader header = dex_file.ReadClassDataHeader(&class_data);
-    size_t num_static_fields = header.static_fields_size_;
-    size_t num_instance_fields = header.instance_fields_size_;
-    size_t num_direct_methods = header.direct_methods_size_;
-    size_t num_virtual_methods = header.virtual_methods_size_;
-
-    if (num_static_fields != 0) {
-      uint32_t last_idx = 0;
-      for (size_t i = 0; i < num_static_fields; ++i) {
-        DexFile::Field dex_field;
-        dex_file.dexReadClassDataField(&class_data, &dex_field, &last_idx);
-        Field* field = class_linker->ResolveField(dex_file, dex_field.field_idx_, dex_cache,
-                                                  class_loader, true);
-        if (field == NULL) {
-          Thread* self = Thread::Current();
-          CHECK(self->IsExceptionPending());
-          self->ClearException();
-        }
-      }
+    if (class_data == NULL) {
+      // empty class such as a marker interface
+      continue;
     }
-    if (num_instance_fields != 0) {
-      uint32_t last_idx = 0;
-      for (size_t i = 0; i < num_instance_fields; ++i) {
-        DexFile::Field dex_field;
-        dex_file.dexReadClassDataField(&class_data, &dex_field, &last_idx);
-        Field* field = class_linker->ResolveField(dex_file, dex_field.field_idx_, dex_cache,
-                                                  class_loader, false);
-        if (field == NULL) {
-          Thread* self = Thread::Current();
-          CHECK(self->IsExceptionPending());
-          self->ClearException();
-        }
+    ClassDataItemIterator it(dex_file, class_data);
+    while (it.HasNextStaticField()) {
+      Field* field = class_linker->ResolveField(dex_file, it.GetMemberIndex(), dex_cache,
+                                                class_loader, true);
+      if (field == NULL) {
+        Thread* self = Thread::Current();
+        CHECK(self->IsExceptionPending());
+        self->ClearException();
       }
+      it.Next();
     }
-    if (num_direct_methods != 0) {
-      uint32_t last_idx = 0;
-      for (size_t i = 0; i < num_direct_methods; ++i) {
-        DexFile::Method dex_method;
-        dex_file.dexReadClassDataMethod(&class_data, &dex_method, &last_idx);
-        Method* method = class_linker->ResolveMethod(dex_file, dex_method.method_idx_, dex_cache,
-                                                     class_loader, true);
-        if (method == NULL) {
-          Thread* self = Thread::Current();
-          CHECK(self->IsExceptionPending());
-          self->ClearException();
-        }
+    while (it.HasNextInstanceField()) {
+      Field* field = class_linker->ResolveField(dex_file, it.GetMemberIndex(), dex_cache,
+                                                class_loader, false);
+      if (field == NULL) {
+        Thread* self = Thread::Current();
+        CHECK(self->IsExceptionPending());
+        self->ClearException();
       }
+      it.Next();
     }
-    if (num_virtual_methods != 0) {
-      uint32_t last_idx = 0;
-      for (size_t i = 0; i < num_virtual_methods; ++i) {
-        DexFile::Method dex_method;
-        dex_file.dexReadClassDataMethod(&class_data, &dex_method, &last_idx);
-        Method* method = class_linker->ResolveMethod(dex_file, dex_method.method_idx_, dex_cache,
-                                                     class_loader, false);
-        if (method == NULL) {
-          Thread* self = Thread::Current();
-          CHECK(self->IsExceptionPending());
-          self->ClearException();
-        }
+    while (it.HasNextDirectMethod()) {
+      Method* method = class_linker->ResolveMethod(dex_file, it.GetMemberIndex(), dex_cache,
+                                                   class_loader, true);
+      if (method == NULL) {
+        Thread* self = Thread::Current();
+        CHECK(self->IsExceptionPending());
+        self->ClearException();
       }
+      it.Next();
     }
+    while (it.HasNextVirtualMethod()) {
+      Method* method = class_linker->ResolveMethod(dex_file, it.GetMemberIndex(), dex_cache,
+                                                   class_loader, false);
+      if (method == NULL) {
+        Thread* self = Thread::Current();
+        CHECK(self->IsExceptionPending());
+        self->ClearException();
+      }
+      it.Next();
+    }
+    DCHECK(!it.HasNext());
   }
 }
 
@@ -278,79 +266,119 @@
 }
 
 void Compiler::CompileDexFile(const ClassLoader* class_loader, const DexFile& dex_file) {
-  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
   for (size_t class_def_index = 0; class_def_index < dex_file.NumClassDefs(); class_def_index++) {
     const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index);
-    const char* descriptor = dex_file.GetClassDescriptor(class_def);
-    Class* klass = class_linker->FindClass(descriptor, class_loader);
-    if (klass == NULL) {
-      // previous verification error will cause FindClass to throw
-      Thread* self = Thread::Current();
-      CHECK(self->IsExceptionPending());
-      self->ClearException();
-    } else {
-      CompileClass(klass);
-    }
+    CompileClass(class_def, class_loader, dex_file);
   }
 }
 
-void Compiler::CompileClass(const Class* klass) {
-  for (size_t i = 0; i < klass->NumDirectMethods(); i++) {
-    CompileMethod(klass->GetDirectMethod(i));
+void Compiler::CompileClass(const DexFile::ClassDef& class_def, const ClassLoader* class_loader,
+                            const DexFile& dex_file) {
+  const byte* class_data = dex_file.GetClassData(class_def);
+  if (class_data == NULL) {
+    // empty class, probably a marker interface
+    return;
   }
-  for (size_t i = 0; i < klass->NumVirtualMethods(); i++) {
-    CompileMethod(klass->GetVirtualMethod(i));
+  ClassDataItemIterator it(dex_file, class_data);
+  // Skip fields
+  while (it.HasNextStaticField()) {
+    it.Next();
   }
+  while (it.HasNextInstanceField()) {
+    it.Next();
+  }
+  // Compile direct methods
+  while (it.HasNextDirectMethod()) {
+    bool is_native = (it.GetMemberAccessFlags() & kAccNative) != 0;
+    bool is_static = (it.GetMemberAccessFlags() & kAccStatic) != 0;
+    bool is_abstract = (it.GetMemberAccessFlags() & kAccAbstract) != 0;
+    CompileMethod(true, is_native, is_static, is_abstract, it.GetMemberIndex(), class_loader,
+                  dex_file);
+    it.Next();
+  }
+  // Compile virtual methods
+  while (it.HasNextVirtualMethod()) {
+    bool is_native = (it.GetMemberAccessFlags() & kAccNative) != 0;
+    bool is_static = (it.GetMemberAccessFlags() & kAccStatic) != 0;
+    bool is_abstract = (it.GetMemberAccessFlags() & kAccAbstract) != 0;
+    CompileMethod(false, is_native, is_static, is_abstract, it.GetMemberIndex(), class_loader,
+                  dex_file);
+    it.Next();
+  }
+  DCHECK(!it.HasNext());
 }
 
-void Compiler::CompileMethod(const Method* method) {
+void Compiler::CompileMethod(bool is_direct, bool is_native, bool is_static, bool is_abstract,
+                             uint32_t method_idx, const ClassLoader* class_loader,
+                             const DexFile& dex_file) {
   CompiledMethod* compiled_method = NULL;
-  if (method->IsNative()) {
-    compiled_method = jni_compiler_.Compile(method);
+  if (is_native) {
+    compiled_method = jni_compiler_.Compile(is_direct, method_idx, class_loader, dex_file);
     CHECK(compiled_method != NULL);
-  } else if (method->IsAbstract()) {
+  } else if (is_abstract) {
   } else {
-    compiled_method = oatCompileMethod(*this, method, kThumb2);
-    CHECK(compiled_method != NULL);
+    compiled_method = oatCompileMethod(*this, is_direct, method_idx, class_loader, dex_file,
+                                       kThumb2);
+    // TODO: assert compiled_method is not NULL, currently NULL may be returned if the method
+    // wasn't resolved
   }
 
   if (compiled_method != NULL) {
-    CHECK(compiled_methods_.find(method) == compiled_methods_.end()) << PrettyMethod(method);
-    compiled_methods_[method] = compiled_method;
-    DCHECK(compiled_methods_.find(method) != compiled_methods_.end()) << PrettyMethod(method);
-    DCHECK(GetCompiledMethod(method) != NULL) << PrettyMethod(method);
+    MethodReference ref(&dex_file, method_idx);
+    CHECK(compiled_methods_.find(ref) == compiled_methods_.end())
+        << PrettyMethod(method_idx, dex_file);
+    compiled_methods_[ref] = compiled_method;
+    DCHECK(compiled_methods_.find(ref) != compiled_methods_.end())
+        << PrettyMethod(method_idx, dex_file);
+    DCHECK(GetCompiledMethod(ref) != NULL)
+        << PrettyMethod(method_idx, dex_file);
   }
 
-  CompiledInvokeStub* compiled_invoke_stub = NULL;
-  if (instruction_set_ == kX86) {
-    compiled_invoke_stub = art::x86::X86CreateInvokeStub(method);
-  } else {
-    CHECK(instruction_set_ == kArm || instruction_set_ == kThumb2);
-    // Generates invocation stub using ARM instruction set
-    compiled_invoke_stub = art::arm::ArmCreateInvokeStub(method);
+  const char* shorty = dex_file.GetMethodShorty(dex_file.GetMethodId(method_idx));
+  const CompiledInvokeStub* compiled_invoke_stub = FindInvokeStub(is_static, shorty);
+  if (compiled_invoke_stub == NULL) {
+    if (instruction_set_ == kX86) {
+      compiled_invoke_stub = art::x86::X86CreateInvokeStub(is_static, shorty);
+    } else {
+      CHECK(instruction_set_ == kArm || instruction_set_ == kThumb2);
+      // Generates invocation stub using ARM instruction set
+      compiled_invoke_stub = art::arm::ArmCreateInvokeStub(is_static, shorty);
+    }
+    CHECK(compiled_invoke_stub != NULL);
+    InsertInvokeStub(is_static, shorty, compiled_invoke_stub);
   }
-  CHECK(compiled_invoke_stub != NULL);
-  // TODO: this fails if we have an abstract method defined in more than one input dex file.
-  CHECK(compiled_invoke_stubs_.find(method) == compiled_invoke_stubs_.end()) << PrettyMethod(method);
-  compiled_invoke_stubs_[method] = compiled_invoke_stub;
-
-  Thread* self = Thread::Current();
-  CHECK(!self->IsExceptionPending()) << PrettyMethod(method);
+  CHECK(!Thread::Current()->IsExceptionPending()) << PrettyMethod(method_idx, dex_file);
 }
 
-const CompiledMethod* Compiler::GetCompiledMethod(const Method* method) const {
-  MethodTable::const_iterator it = compiled_methods_.find(method);
-  if (it == compiled_methods_.end()) {
-    return NULL;
+static std::string MakeInvokeStubKey(bool is_static, const char* shorty) {
+  std::string key(shorty);
+  if (is_static) {
+    key += "$";  // musn't be a shorty type character
   }
-  CHECK(it->second != NULL);
-  return it->second;
+  return key;
 }
 
-const CompiledInvokeStub* Compiler::GetCompiledInvokeStub(const Method* method) const {
-  InvokeStubTable::const_iterator it = compiled_invoke_stubs_.find(method);
+const CompiledInvokeStub* Compiler::FindInvokeStub(bool is_static, const char* shorty) const {
+  std::string key = MakeInvokeStubKey(is_static, shorty);
+  InvokeStubTable::const_iterator it = compiled_invoke_stubs_.find(key);
   if (it == compiled_invoke_stubs_.end()) {
     return NULL;
+  } else {
+    DCHECK(it->second != NULL);
+    return it->second;
+  }
+}
+
+void Compiler::InsertInvokeStub(bool is_static, const char* shorty,
+                                const CompiledInvokeStub* compiled_invoke_stub) {
+  std::string key = MakeInvokeStubKey(is_static, shorty);
+  compiled_invoke_stubs_[key] = compiled_invoke_stub;
+}
+
+CompiledMethod* Compiler::GetCompiledMethod(MethodReference ref) const {
+  MethodTable::const_iterator it = compiled_methods_.find(ref);
+  if (it == compiled_methods_.end()) {
+    return NULL;
   }
   CHECK(it->second != NULL);
   return it->second;
diff --git a/src/compiler.h b/src/compiler.h
index 55bab59..f29fbbc 100644
--- a/src/compiler.h
+++ b/src/compiler.h
@@ -12,6 +12,8 @@
 #include "runtime.h"
 #include "unordered_map.h"
 
+#include <string>
+
 namespace art {
 
 class Compiler {
@@ -52,8 +54,11 @@
   static ByteArray* CreateResolutionStub(InstructionSet instruction_set,
                                          Runtime::TrampolineType type);
 
-  const CompiledMethod* GetCompiledMethod(const Method* method) const;
-  const CompiledInvokeStub* GetCompiledInvokeStub(const Method* method) const;
+  // A method is uniquely located by its DexFile and index into the method_id table of that dex file
+  typedef std::pair<const DexFile*, uint32_t> MethodReference;
+
+  CompiledMethod* GetCompiledMethod(MethodReference ref) const;
+  const CompiledInvokeStub* FindInvokeStub(bool is_static, const char* shorty) const;
 
   // Callbacks from OAT/ART compiler to see what runtime checks must be generated
   bool CanAssumeTypeIsPresentInDexCache(const Method* referrer, uint32_t type_idx) const {
@@ -70,6 +75,7 @@
     DCHECK(resolved_class == NULL || referrer->GetDeclaringClass()->CanAccess(resolved_class));
     return resolved_class != NULL;
   }
+
  private:
   // Attempt to resolve all type, methods, fields, and strings
   // referenced from code in the dex file following PathClassLoader
@@ -85,21 +91,41 @@
 
   void Compile(const ClassLoader* class_loader);
   void CompileDexFile(const ClassLoader* class_loader, const DexFile& dex_file);
-  void CompileClass(const Class* klass);
-  void CompileMethod(const Method* method);
+  void CompileClass(const DexFile::ClassDef& class_def, const ClassLoader* class_loader,
+                    const DexFile& dex_file);
+  void CompileMethod(bool is_direct, bool is_native, bool is_static, bool is_abstract,
+                     uint32_t method_idx, const ClassLoader* class_loader, const DexFile& dex_file);
 
   // After compiling, walk all the DexCaches and set the code and
   // method pointers of CodeAndDirectMethods entries in the DexCaches.
   void SetCodeAndDirectMethods(const ClassLoader* class_loader);
   void SetCodeAndDirectMethodsDexFile(const DexFile& dex_file);
 
+  void InsertInvokeStub(bool is_static, const char* shorty,
+                        const CompiledInvokeStub* compiled_invoke_stub);
+
   InstructionSet instruction_set_;
   JniCompiler jni_compiler_;
 
-  typedef std::tr1::unordered_map<const Method*, CompiledMethod*, ObjectIdentityHash> MethodTable;
+  struct MethodReferenceHash {
+    size_t operator()(const MethodReference id) const {
+      size_t dex = reinterpret_cast<size_t>(id.first);
+      DCHECK_NE(dex, static_cast<size_t>(0));
+      dex += 33;  // dex is an aligned pointer, get some non-zero low bits
+      size_t idx = id.second;
+      if (idx == 0) {  // special case of a method index of 0
+        return dex * 5381;
+      } else {
+        return dex * idx;
+      }
+    }
+  };
+  typedef std::tr1::unordered_map<const MethodReference, CompiledMethod*, MethodReferenceHash> MethodTable;
+  // All method references that this compiler has compiled
   MethodTable compiled_methods_;
 
-  typedef std::tr1::unordered_map<const Method*, CompiledInvokeStub*, ObjectIdentityHash> InvokeStubTable;
+  typedef std::tr1::unordered_map<std::string, const CompiledInvokeStub*> InvokeStubTable;
+  // Invocation stubs created to allow invocation of the compiled methods
   InvokeStubTable compiled_invoke_stubs_;
 
   bool image_;
diff --git a/src/compiler/Compiler.h b/src/compiler/Compiler.h
index 28a689f..917e3fd 100644
--- a/src/compiler/Compiler.h
+++ b/src/compiler/Compiler.h
@@ -17,6 +17,8 @@
 #ifndef ART_SRC_COMPILER_COMPILER_H_
 #define ART_SRC_COMPILER_COMPILER_H_
 
+#include "dex_file.h"
+
 #define COMPILER_TRACED(X)
 #define COMPILER_TRACEE(X)
 
@@ -99,9 +101,9 @@
 void oatArchDump(void);
 bool oatStartup(void);
 void oatShutdown(void);
-CompiledMethod* oatCompileMethod(const Compiler& compiler,
-                                 const Method* method,
-                                 OatInstructionSetType);
+CompiledMethod* oatCompileMethod(const Compiler& compiler, bool is_direct,
+                                 uint32_t method_idx, const art::ClassLoader* class_loader,
+                                 const art::DexFile& dex_file, OatInstructionSetType);
 void oatDumpStats(void);
 void oatScanAllClassPointers(void (*callback)(void* ptr));
 void oatInitializeSSAConversion(struct CompilationUnit* cUnit);
diff --git a/src/compiler/Frontend.cc b/src/compiler/Frontend.cc
index d4f1b27..9a2cc31 100644
--- a/src/compiler/Frontend.cc
+++ b/src/compiler/Frontend.cc
@@ -18,6 +18,7 @@
 #include "CompilerInternals.h"
 #include "Dataflow.h"
 #include "constants.h"
+#include "leb128.h"
 #include "object.h"
 #include "runtime.h"
 
@@ -432,7 +433,7 @@
 
     for (int i = 0; i < triesSize; i++) {
         const art::DexFile::TryItem* pTry =
-            art::DexFile::dexGetTryItems(*code_item, i);
+            art::DexFile::GetTryItems(*code_item, i);
         int startOffset = pTry->start_addr_;
         int endOffset = startOffset + pTry->insn_count_;
         for (offset = startOffset; offset < endOffset; offset++) {
@@ -442,16 +443,15 @@
 
     // Iterate over each of the handlers to enqueue the empty Catch blocks
     const art::byte* handlers_ptr =
-        art::DexFile::dexGetCatchHandlerData(*code_item, 0);
+        art::DexFile::GetCatchHandlerData(*code_item, 0);
     uint32_t handlers_size = art::DecodeUnsignedLeb128(&handlers_ptr);
     for (uint32_t idx = 0; idx < handlers_size; idx++) {
-        art::DexFile::CatchHandlerIterator iterator(handlers_ptr);
-
-        for (; !iterator.HasNext(); iterator.Next()) {
-            uint32_t address = iterator.Get().address_;
+        art::CatchHandlerIterator iterator(handlers_ptr);
+        for (; iterator.HasNext(); iterator.Next()) {
+            uint32_t address = iterator.GetHandlerAddress();
             findBlock(cUnit, address, false /* split */, true /*create*/);
         }
-        handlers_ptr = iterator.GetData();
+        handlers_ptr = iterator.EndDataPointer();
     }
 }
 
@@ -625,8 +625,7 @@
 
     /* In try block */
     if (oatIsBitSet(tryBlockAddr, curOffset)) {
-        art::DexFile::CatchHandlerIterator iterator =
-            art::DexFile::dexFindCatchHandler(*code_item, curOffset);
+        art::CatchHandlerIterator iterator(*code_item, curOffset);
 
         if (curBlock->successorBlockList.blockListType != kNotUsed) {
             LOG(FATAL) << "Successor block list already in use: " <<
@@ -636,8 +635,8 @@
         curBlock->successorBlockList.blockListType = kCatch;
         oatInitGrowableList(&curBlock->successorBlockList.blocks, 2);
 
-        for (;!iterator.HasNext(); iterator.Next()) {
-            BasicBlock *catchBlock = findBlock(cUnit, iterator.Get().address_,
+        for (;iterator.HasNext(); iterator.Next()) {
+            BasicBlock *catchBlock = findBlock(cUnit, iterator.GetHandlerAddress(),
                                                false /* split*/,
                                                false /* creat */);
             catchBlock->catchEntry = true;
@@ -645,7 +644,7 @@
                   (SuccessorBlockInfo *) oatNew(sizeof(SuccessorBlockInfo),
                   false);
             successorBlockInfo->block = catchBlock;
-            successorBlockInfo->key = iterator.Get().type_idx_;
+            successorBlockInfo->key = iterator.GetHandlerTypeIndex();
             oatInsertGrowableList(&curBlock->successorBlockList.blocks,
                                   (intptr_t) successorBlockInfo);
             oatSetBit(catchBlock->predecessors, curBlock->id);
@@ -692,16 +691,26 @@
 /*
  * Compile a method.
  */
-CompiledMethod* oatCompileMethod(const Compiler& compiler, const Method* method, art::InstructionSet insnSet)
+CompiledMethod* oatCompileMethod(const Compiler& compiler, bool is_direct,
+                                      uint32_t method_idx, const art::ClassLoader* class_loader,
+                                      const art::DexFile& dex_file, art::InstructionSet insnSet)
 {
+    art::ClassLinker* linker = art::Runtime::Current()->GetClassLinker();
+    art::DexCache* dex_cache = linker->FindDexCache(dex_file);
+    art::Method* method = linker->ResolveMethod(dex_file, method_idx, dex_cache,
+                                                class_loader, is_direct);
+    if (method == NULL) {
+      CHECK(Thread::Current()->IsExceptionPending());
+      Thread::Current()->ClearException();
+      LOG(INFO) << "Couldn't resolve " << PrettyMethod(method_idx, dex_file, true)
+          << " for compilation";
+      return NULL;
+    }
     if (compiler.IsVerbose()) {
         LOG(INFO) << "Compiling " << PrettyMethod(method) << "...";
     }
     oatArenaReset();
 
-    art::ClassLinker* class_linker = art::Runtime::Current()->GetClassLinker();
-    const art::DexFile& dex_file = class_linker->FindDexFile(
-         method->GetDeclaringClass()->GetDexCache());
     const art::DexFile::CodeItem* code_item =
          dex_file.GetCodeItem(method->GetCodeItemOffset());
     const u2* codePtr = code_item->insns_;
@@ -907,9 +916,10 @@
                                     + __builtin_popcount(cUnit->fpSpillMask)));
     DCHECK_GE(vmapTable.size(), 1U);  // should always at least one INVALID_VREG for lr
 
-    CompiledMethod* result = new CompiledMethod(art::kThumb2,
-        cUnit->codeBuffer, cUnit->frameSize, cUnit->frameSize - sizeof(intptr_t),
-        cUnit->coreSpillMask, cUnit->fpSpillMask, cUnit->mappingTable, vmapTable);
+    CompiledMethod* result = new CompiledMethod(art::kThumb2, cUnit->codeBuffer,
+                                                cUnit->frameSize, cUnit->coreSpillMask,
+                                                cUnit->fpSpillMask, cUnit->mappingTable,
+                                                vmapTable);
 
     if (compiler.IsVerbose()) {
         LOG(INFO) << "Compiled " << PrettyMethod(method)
diff --git a/src/compiler/codegen/arm/Thumb2/Gen.cc b/src/compiler/codegen/arm/Thumb2/Gen.cc
index bff53be..006be69 100644
--- a/src/compiler/codegen/arm/Thumb2/Gen.cc
+++ b/src/compiler/codegen/arm/Thumb2/Gen.cc
@@ -39,8 +39,8 @@
     const art::DexFile& dex_file = class_linker->FindDexFile(
          method->GetDeclaringClass()->GetDexCache());
     const art::DexFile::FieldId& field_id = dex_file.GetFieldId(fieldIdx);
-    std::string class_name = dex_file.dexStringByTypeIdx(field_id.class_idx_);
-    std::string field_name = dex_file.dexStringById(field_id.name_idx_);
+    std::string class_name = dex_file.StringByTypeIdx(field_id.class_idx_);
+    std::string field_name = dex_file.StringDataByIdx(field_id.name_idx_);
     return class_name + "." + field_name;
 }
 
diff --git a/src/dex_cache.cc b/src/dex_cache.cc
index 4eb18a5..c43f5bf 100644
--- a/src/dex_cache.cc
+++ b/src/dex_cache.cc
@@ -9,6 +9,14 @@
 
 namespace art {
 
+void CodeAndDirectMethods::SetResolvedDirectMethod(uint32_t method_idx, Method* method) {
+  CHECK(method != NULL);
+  CHECK(method->IsDirect()) << PrettyMethod(method);
+  CHECK(method->GetCode() != NULL) << PrettyMethod(method);
+  Set(CodeIndex(method_idx),   reinterpret_cast<int32_t>(method->GetCode()));
+  Set(MethodIndex(method_idx), reinterpret_cast<int32_t>(method));
+}
+
 void DexCache::Init(String* location,
                     ObjectArray<String>* strings,
                     ObjectArray<Class>* resolved_types,
diff --git a/src/dex_cache.h b/src/dex_cache.h
index ee1731a..8cd9b12 100644
--- a/src/dex_cache.h
+++ b/src/dex_cache.h
@@ -33,13 +33,7 @@
     Set(MethodIndex(method_idx), method_idx);
   }
 
-  void SetResolvedDirectMethod(uint32_t method_idx, Method* method) {
-    CHECK(method != NULL);
-    CHECK(method->IsDirect()) << PrettyMethod(method);
-    CHECK(method->GetCode() != NULL) << PrettyMethod(method);
-    Set(CodeIndex(method_idx),   reinterpret_cast<int32_t>(method->GetCode()));
-    Set(MethodIndex(method_idx), reinterpret_cast<int32_t>(method));
-  }
+  void SetResolvedDirectMethod(uint32_t method_idx, Method* method);
 
   static size_t LengthAsArray(size_t elements) {
     return kMax * elements;
diff --git a/src/dex_file.cc b/src/dex_file.cc
index 21489dd..e9a883c 100644
--- a/src/dex_file.cc
+++ b/src/dex_file.cc
@@ -14,12 +14,15 @@
 #include <map>
 
 #include "UniquePtr.h"
+#include "class_linker.h"
 #include "globals.h"
+#include "leb128.h"
 #include "logging.h"
 #include "object.h"
 #include "os.h"
 #include "stringprintf.h"
 #include "thread.h"
+#include "utf.h"
 #include "utils.h"
 #include "zip_archive.h"
 
@@ -421,6 +424,19 @@
   return atoi(version);
 }
 
+int32_t DexFile::GetStringLength(const StringId& string_id) const {
+  const byte* ptr = base_ + string_id.string_data_off_;
+  return DecodeUnsignedLeb128(&ptr);
+}
+
+// Returns a pointer to the UTF-8 string data referred to by the given string_id.
+const char* DexFile::GetStringDataAndLength(const StringId& string_id, int32_t* length) const {
+  CHECK(length != NULL);
+  const byte* ptr = base_ + string_id.string_data_off_;
+  *length = DecodeUnsignedLeb128(&ptr);
+  return reinterpret_cast<const char*>(ptr);
+}
+
 void DexFile::InitIndex() {
   CHECK_EQ(index_.size(), 0U);
   for (size_t i = 0; i < NumClassDefs(); ++i) {
@@ -447,11 +463,172 @@
   return NULL;
 }
 
+const DexFile::MethodId* DexFile::FindMethodId(const DexFile::TypeId& klass,
+                                               const DexFile::StringId& name,
+                                               const DexFile::ProtoId& signature) const {
+  // Binary search MethodIds knowing that they are sorted by class_idx, name_idx then proto_idx
+  const uint16_t class_idx = GetIndexForTypeId(klass);
+  const uint32_t name_idx = GetIndexForStringId(name);
+  const uint16_t proto_idx = GetIndexForProtoId(signature);
+  uint32_t lo = 0;
+  uint32_t hi = NumMethodIds() - 1;
+  while (hi >= lo) {
+    uint32_t mid = (hi + lo) / 2;
+    const DexFile::MethodId& method = GetMethodId(mid);
+    if (class_idx > method.class_idx_) {
+      lo = mid + 1;
+    } else if (class_idx < method.class_idx_) {
+      hi = mid - 1;
+    } else {
+      if (name_idx > method.name_idx_) {
+        lo = mid + 1;
+      } else if (name_idx < method.name_idx_) {
+        hi = mid - 1;
+      } else {
+        if (proto_idx > method.proto_idx_) {
+          lo = mid + 1;
+        } else if (proto_idx < method.proto_idx_) {
+          hi = mid - 1;
+        } else {
+          return &method;
+        }
+      }
+    }
+  }
+  return NULL;
+}
+
+const DexFile::StringId* DexFile::FindStringId(const std::string& string) const {
+  uint32_t lo = 0;
+  uint32_t hi = NumStringIds() - 1;
+  while (hi >= lo) {
+    uint32_t mid = (hi + lo) / 2;
+    int32_t length;
+    const DexFile::StringId& str_id = GetStringId(mid);
+    const char* str = GetStringDataAndLength(str_id, &length);
+    int compare = CompareModifiedUtf8ToModifiedUtf8AsUtf16CodePointValues(string.c_str(), str);
+    if (compare > 0) {
+      lo = mid + 1;
+    } else if (compare < 0) {
+      hi = mid - 1;
+    } else {
+      return &str_id;
+    }
+  }
+  return NULL;
+}
+
+const DexFile::TypeId* DexFile::FindTypeId(uint32_t string_idx) const {
+  uint32_t lo = 0;
+  uint32_t hi = NumTypeIds() - 1;
+  while (hi >= lo) {
+    uint32_t mid = (hi + lo) / 2;
+    const TypeId& type_id = GetTypeId(mid);
+    if (string_idx > type_id.descriptor_idx_) {
+      lo = mid + 1;
+    } else if (string_idx < type_id.descriptor_idx_) {
+      hi = mid - 1;
+    } else {
+      return &type_id;
+    }
+  }
+  return NULL;
+}
+
+const DexFile::ProtoId* DexFile::FindProtoId(uint16_t return_type_idx,
+                                             const std::vector<uint16_t>& signature_type_ids) const {
+  uint32_t lo = 0;
+  uint32_t hi = NumProtoIds() - 1;
+  while (hi >= lo) {
+    uint32_t mid = (hi + lo) / 2;
+    const DexFile::ProtoId& proto = GetProtoId(mid);
+    int compare = return_type_idx - proto.return_type_idx_;
+    if (compare == 0) {
+      DexFileParameterIterator it(*this, proto);
+      size_t i = 0;
+      while (it.HasNext() && i < signature_type_ids.size() && compare == 0) {
+        compare = signature_type_ids[i] - it.GetTypeId();
+        it.Next();
+        i++;
+      }
+      if (compare == 0) {
+        if (it.HasNext()) {
+          compare = -1;
+        } else if (i < signature_type_ids.size()) {
+          compare = 1;
+        }
+      }
+    }
+    if (compare > 0) {
+      lo = mid + 1;
+    } else if (compare < 0) {
+      hi = mid - 1;
+    } else {
+      return &proto;
+    }
+  }
+  return NULL;
+}
+
+// Given a signature place the type ids into the given vector
+bool DexFile::CreateTypeList(uint16_t* return_type_idx, std::vector<uint16_t>* param_type_idxs,
+                             const std::string& signature) const {
+  if (signature[0] != '(') {
+    return false;
+  }
+  size_t offset = 1;
+  size_t end = signature.size();
+  bool process_return = false;
+  while (offset < end) {
+    char c = signature[offset];
+    offset++;
+    if (c == ')') {
+      process_return = true;
+      continue;
+    }
+    std::string descriptor;
+    descriptor += c;
+    while (c == '[') {  // process array prefix
+      if (offset >= end) {  // expect some descriptor following [
+        return false;
+      }
+      c = signature[offset];
+      offset++;
+      descriptor += c;
+    }
+    if (c == 'L') {  // process type descriptors
+      do {
+        if (offset >= end) {  // unexpected early termination of descriptor
+          return false;
+        }
+        c = signature[offset];
+        offset++;
+        descriptor += c;
+      } while (c != ';');
+    }
+    const DexFile::StringId* string_id = FindStringId(descriptor);
+    if (string_id == NULL) {
+      return false;
+    }
+    const DexFile::TypeId* type_id = FindTypeId(GetIndexForStringId(*string_id));
+    if (type_id == NULL) {
+      return false;
+    }
+    uint16_t type_idx = GetIndexForTypeId(*type_id);
+    if (!process_return) {
+      param_type_idxs->push_back(type_idx);
+    } else {
+      *return_type_idx = type_idx;
+      return offset == end;  // return true if the signature had reached a sensible end
+    }
+  }
+  return false;  // failed to correctly parse return type
+}
+
 // Materializes the method descriptor for a method prototype.  Method
 // descriptors are not stored directly in the dex file.  Instead, one
 // must assemble the descriptor from references in the prototype.
-std::string DexFile::CreateMethodDescriptor(uint32_t proto_idx,
-    int32_t* unicode_length) const {
+std::string DexFile::CreateMethodSignature(uint32_t proto_idx, int32_t* unicode_length) const {
   const ProtoId& proto_id = GetProtoId(proto_idx);
   std::string descriptor;
   descriptor.push_back('(');
@@ -463,7 +640,7 @@
       const TypeItem& type_item = type_list->GetTypeItem(i);
       uint32_t type_idx = type_item.type_idx_;
       int32_t type_length;
-      const char* name = dexStringByTypeIdx(type_idx, &type_length);
+      const char* name = StringByTypeIdx(type_idx, &type_length);
       parameter_length += type_length;
       descriptor.append(name);
     }
@@ -471,7 +648,7 @@
   descriptor.push_back(')');
   uint32_t return_type_idx = proto_id.return_type_idx_;
   int32_t return_type_length;
-  const char* name = dexStringByTypeIdx(return_type_idx, &return_type_length);
+  const char* name = StringByTypeIdx(return_type_idx, &return_type_length);
   descriptor.append(name);
   if (unicode_length != NULL) {
     *unicode_length = parameter_length + return_type_length + 2;  // 2 for ( and )
@@ -479,127 +656,6 @@
   return descriptor;
 }
 
-// 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;
-}
-
-DexFile::ValueType DexFile::ReadEncodedValue(const byte** stream,
-                                             JValue* value) const {
-  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 DexFile::kByte: {
-      int32_t b = ReadSignedInt(ptr, value_arg);
-      CHECK(IsInt(8, b));
-      value->i = b;
-      break;
-    }
-    case DexFile::kShort: {
-      int32_t s = ReadSignedInt(ptr, value_arg);
-      CHECK(IsInt(16, s));
-      value->i = s;
-      break;
-    }
-    case DexFile::kChar: {
-      uint32_t c = ReadUnsignedInt(ptr, value_arg, false);
-      CHECK(IsUint(16, c));
-      value->i = c;
-      break;
-    }
-    case DexFile::kInt:
-      value->i = ReadSignedInt(ptr, value_arg);
-      break;
-    case DexFile::kLong:
-      value->j = ReadSignedLong(ptr, value_arg);
-      break;
-    case DexFile::kFloat:
-      value->i = ReadUnsignedInt(ptr, value_arg, true);
-      break;
-    case DexFile::kDouble:
-      value->j = ReadUnsignedLong(ptr, value_arg, true);
-      break;
-    case DexFile::kBoolean:
-      value->i = (value_arg != 0);
-      width = 0;
-      break;
-    case DexFile::kString:
-    case DexFile::kType:
-    case DexFile::kMethod:
-    case DexFile::kEnum:
-      value->i = ReadUnsignedInt(ptr, value_arg, false);
-      break;
-    case DexFile::kField:
-    case DexFile::kArray:
-    case DexFile::kAnnotation:
-      UNIMPLEMENTED(FATAL) << ": type " << type;
-      break;
-    case DexFile::kNull:
-      value->i = 0;
-      width = 0;
-      break;
-    default:
-      LOG(FATAL) << "Unreached";
-  }
-  ptr += width;
-  *stream = ptr;
-  return static_cast<ValueType>(type);
-}
 
 int32_t DexFile::GetLineNumFromPC(const art::Method* method, uint32_t rel_pc) const {
   // For native method, lineno should be -2 to indicate it is native. Note that
@@ -613,13 +669,38 @@
 
   // A method with no line number info should return -1
   LineNumFromPcContext context(rel_pc, -1);
-  dexDecodeDebugInfo(code_item, method, LineNumForPcCb, NULL, &context);
+  DecodeDebugInfo(code_item, method, LineNumForPcCb, NULL, &context);
   return context.line_num_;
 }
 
-void DexFile::dexDecodeDebugInfo0(const CodeItem* code_item, const art::Method* method,
-                         DexDebugNewPositionCb posCb, DexDebugNewLocalCb local_cb,
-                         void* cnxt, const byte* stream, LocalInfo* local_in_reg) const {
+int32_t DexFile::FindCatchHandlerOffset(const CodeItem &code_item, int32_t tries_size,
+                                        uint32_t address){
+  // Note: Signed type is important for max and min.
+  int32_t min = 0;
+  int32_t max = tries_size - 1;
+
+  while (max >= min) {
+    int32_t mid = (min + max) / 2;
+    const TryItem* pTry = DexFile::GetTryItems(code_item, mid);
+    uint32_t start = pTry->start_addr_;
+    if (address < start) {
+      max = mid - 1;
+    } else {
+      uint32_t end = start + pTry->insn_count_;
+      if (address >= end) {
+        min = mid + 1;
+      } else {  // We have a winner!
+        return (int32_t) pTry->handler_off_;
+      }
+    }
+  }
+  // No match.
+  return -1;
+}
+
+void DexFile::DecodeDebugInfo0(const CodeItem* code_item, const Method* method,
+                               DexDebugNewPositionCb posCb, DexDebugNewLocalCb local_cb,
+                               void* cnxt, const byte* stream, LocalInfo* local_in_reg) const {
   uint32_t line = DecodeUnsignedLeb128(&stream);
   uint32_t parameters_size = DecodeUnsignedLeb128(&stream);
   uint16_t arg_reg = code_item->registers_size_ - code_item->ins_size_;
@@ -639,17 +720,17 @@
     arg_reg++;
   }
 
-  ParameterIterator* it = GetParameterIterator(GetProtoId(method->GetProtoIdx()));
-  for (uint32_t i = 0; i < parameters_size && it->HasNext(); ++i, it->Next()) {
+  DexFileParameterIterator it(*this, GetProtoId(method->GetProtoIdx()));
+  for (uint32_t i = 0; i < parameters_size && it.HasNext(); ++i, it.Next()) {
     if (arg_reg >= code_item->registers_size_) {
       LOG(ERROR) << "invalid stream - arg reg >= reg size (" << arg_reg
                  << " >= " << code_item->registers_size_ << ")";
       return;
     }
     int32_t id = DecodeUnsignedLeb128P1(&stream);
-    const char* descriptor = it->GetDescriptor();
+    const char* descriptor = it.GetDescriptor();
     if (need_locals) {
-      const char* name = dexStringById(id);
+      const char* name = StringDataByIdx(id);
       local_in_reg[arg_reg].name_ = name;
       local_in_reg[arg_reg].descriptor_ = descriptor;
       local_in_reg[arg_reg].start_address_ = address;
@@ -666,7 +747,7 @@
     }
   }
 
-  if (it->HasNext()) {
+  if (it.HasNext()) {
     LOG(ERROR) << "invalid stream - problem with parameter iterator";
     return;
   }
@@ -709,10 +790,10 @@
         if (need_locals) {
           InvokeLocalCbIfLive(cnxt, reg, address, local_in_reg, local_cb);
 
-          local_in_reg[reg].name_ = dexStringById(name_idx);
-          local_in_reg[reg].descriptor_ = dexStringByTypeIdx(descriptor_idx);
+          local_in_reg[reg].name_ = StringDataByIdx(name_idx);
+          local_in_reg[reg].descriptor_ = StringByTypeIdx(descriptor_idx);
           if (opcode == DBG_START_LOCAL_EXTENDED) {
-            local_in_reg[reg].signature_ = dexStringById(signature_idx);
+            local_in_reg[reg].signature_ = StringDataByIdx(signature_idx);
           }
           local_in_reg[reg].start_address_ = address;
           local_in_reg[reg].is_live_ = true;
@@ -779,4 +860,270 @@
   }
 }
 
+void DexFile::DecodeDebugInfo(const CodeItem* code_item, const art::Method* method,
+                                 DexDebugNewPositionCb posCb, DexDebugNewLocalCb local_cb,
+                                 void* cnxt) const {
+  const byte* stream = GetDebugInfoStream(code_item);
+  LocalInfo local_in_reg[code_item->registers_size_];
+
+  if (stream != NULL) {
+    DecodeDebugInfo0(code_item, method, posCb, local_cb, cnxt, stream, local_in_reg);
+  }
+  for (int reg = 0; reg < code_item->registers_size_; reg++) {
+    InvokeLocalCbIfLive(cnxt, reg, code_item->insns_size_in_code_units_, local_in_reg, local_cb);
+  }
+}
+
+bool DexFile::LineNumForPcCb(void* cnxt, uint32_t address, uint32_t line_num) {
+  LineNumFromPcContext* context = (LineNumFromPcContext*) cnxt;
+
+  // We know that this callback will be called in
+  // ascending address order, so keep going until we find
+  // a match or we've just gone past it.
+  if (address > context->address_) {
+    // The line number from the previous positions callback
+    // wil be the final result.
+    return true;
+  } else {
+    context->line_num_ = line_num;
+    return address == context->address_;
+  }
+}
+
+// Decodes the header section from the class data bytes.
+void ClassDataItemIterator::ReadClassDataHeader() {
+  CHECK(ptr_pos_ != NULL);
+  header_.static_fields_size_ = DecodeUnsignedLeb128(&ptr_pos_);
+  header_.instance_fields_size_ = DecodeUnsignedLeb128(&ptr_pos_);
+  header_.direct_methods_size_ = DecodeUnsignedLeb128(&ptr_pos_);
+  header_.virtual_methods_size_ = DecodeUnsignedLeb128(&ptr_pos_);
+}
+
+void ClassDataItemIterator::ReadClassDataField() {
+  field_.field_idx_delta_ = DecodeUnsignedLeb128(&ptr_pos_);
+  field_.access_flags_ = DecodeUnsignedLeb128(&ptr_pos_);
+}
+
+void ClassDataItemIterator::ReadClassDataMethod() {
+  method_.method_idx_delta_ = DecodeUnsignedLeb128(&ptr_pos_);
+  method_.access_flags_ = DecodeUnsignedLeb128(&ptr_pos_);
+  method_.code_off_ = DecodeUnsignedLeb128(&ptr_pos_);
+}
+
+// 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;
+}
+
+EncodedStaticFieldValueIterator::EncodedStaticFieldValueIterator(const DexFile& dex_file,
+    DexCache* dex_cache, ClassLinker* linker, const DexFile::ClassDef& class_def) :
+    dex_file_(dex_file), dex_cache_(dex_cache), linker_(linker), array_size_(), pos_(-1), type_(0) {
+  ptr_ = dex_file.GetEncodedStaticFieldValuesArray(class_def);
+  if (ptr_ == NULL) {
+    array_size_ = 0;
+  } else {
+    array_size_ = DecodeUnsignedLeb128(&ptr_);
+  }
+  if (array_size_ > 0) {
+    Next();
+  }
+}
+
+void EncodedStaticFieldValueIterator::Next() {
+  pos_++;
+  if (pos_ >= array_size_) {
+    return;
+  }
+  byte value_type = *ptr_++;
+  byte value_arg = value_type >> kEncodedValueArgShift;
+  size_t width = value_arg + 1;  // assume and correct later
+  type_ = value_type & kEncodedValueTypeMask;
+  switch (type_) {
+  case kBoolean:
+    jval_.i = (value_arg != 0) ? 1 : 0;
+    width = 0;
+    break;
+  case kByte:
+    jval_.i = ReadSignedInt(ptr_, value_arg);
+    CHECK(IsInt(8, jval_.i));
+    break;
+  case kShort:
+    jval_.i = ReadSignedInt(ptr_, value_arg);
+    CHECK(IsInt(16, jval_.i));
+    break;
+  case kChar:
+    jval_.i = ReadUnsignedInt(ptr_, value_arg, false);
+    CHECK(IsUint(16, jval_.i));
+    break;
+  case kInt:
+    jval_.i = ReadSignedInt(ptr_, value_arg);
+    break;
+  case kLong:
+    jval_.j = ReadSignedLong(ptr_, value_arg);
+    break;
+  case kFloat:
+    jval_.i = ReadUnsignedInt(ptr_, value_arg, true);
+    break;
+  case kDouble:
+    jval_.j = ReadUnsignedLong(ptr_, value_arg, true);
+    break;
+  case kString:
+  case kType:
+  case kMethod:
+  case kEnum:
+    jval_.i = ReadUnsignedInt(ptr_, value_arg, false);
+    break;
+  case kField:
+  case kArray:
+  case kAnnotation:
+    UNIMPLEMENTED(FATAL) << ": type " << type_;
+    break;
+  case kNull:
+    jval_.l = NULL;
+    width = 0;
+    break;
+  default:
+    LOG(FATAL) << "Unreached";
+  }
+  ptr_ += width;
+}
+
+void EncodedStaticFieldValueIterator::ReadValueToField(Field* field) const {
+  switch (type_) {
+    case kBoolean: field->SetBoolean(NULL, jval_.z); break;
+    case kByte:    field->SetByte(NULL, jval_.b); break;
+    case kShort:   field->SetShort(NULL, jval_.s); break;
+    case kChar:    field->SetChar(NULL, jval_.c); break;
+    case kInt:     field->SetInt(NULL, jval_.i); break;
+    case kLong:    field->SetLong(NULL, jval_.j); break;
+    case kFloat:   field->SetFloat(NULL, jval_.f); break;
+    case kDouble:  field->SetDouble(NULL, jval_.d); break;
+    case kNull:    field->SetObject(NULL, NULL); break;
+    case kString: {
+      String* resolved = linker_->ResolveString(dex_file_, jval_.i, dex_cache_);
+      field->SetObject(NULL, resolved);
+      break;
+    }
+    default: UNIMPLEMENTED(FATAL) << ": type " << type_;
+  }
+}
+
+CatchHandlerIterator::CatchHandlerIterator(const DexFile::CodeItem& code_item, uint32_t address) {
+  handler_.address_ = -1;
+  int32_t offset = -1;
+
+  // Short-circuit the overwhelmingly common cases.
+  switch (code_item.tries_size_) {
+    case 0:
+      break;
+    case 1: {
+      const DexFile::TryItem* tries = DexFile::GetTryItems(code_item, 0);
+      uint32_t start = tries->start_addr_;
+      if (address >= start) {
+        uint32_t end = start + tries->insn_count_;
+        if (address < end) {
+          offset = tries->handler_off_;
+        }
+      }
+      break;
+    }
+    default:
+      offset = DexFile::FindCatchHandlerOffset(code_item, code_item.tries_size_, address);
+  }
+  if (offset >= 0) {
+    const byte* handler_data = DexFile::GetCatchHandlerData(code_item, offset);
+    Init(handler_data);
+  } else {
+    // Not found, initialize as empty
+    current_data_ = NULL;
+    remaining_count_ = -1;
+    catch_all_ = false;
+    DCHECK(!HasNext());
+  }
+}
+
+void CatchHandlerIterator::Init(const byte* handler_data) {
+  current_data_ = handler_data;
+  remaining_count_ = DecodeSignedLeb128(&current_data_);
+
+  // If remaining_count_ is non-positive, then it is the negative of
+  // the number of catch types, and the catches are followed by a
+  // catch-all handler.
+  if (remaining_count_ <= 0) {
+    catch_all_ = true;
+    remaining_count_ = -remaining_count_;
+  } else {
+    catch_all_ = false;
+  }
+  Next();
+}
+
+void CatchHandlerIterator::Next() {
+  if (remaining_count_ > 0) {
+    handler_.type_idx_ = DecodeUnsignedLeb128(&current_data_);
+    handler_.address_  = DecodeUnsignedLeb128(&current_data_);
+    remaining_count_--;
+    return;
+  }
+
+  if (catch_all_) {
+    handler_.type_idx_ = DexFile::kDexNoIndex16;
+    handler_.address_  = DecodeUnsignedLeb128(&current_data_);
+    catch_all_ = false;
+    return;
+  }
+
+  // no more handler
+  remaining_count_ = -1;
+}
+
 }  // namespace art
diff --git a/src/dex_file.h b/src/dex_file.h
index 3acd79f..62b99ab 100644
--- a/src/dex_file.h
+++ b/src/dex_file.h
@@ -10,20 +10,14 @@
 #include "UniquePtr.h"
 #include "globals.h"
 #include "jni.h"
-#include "leb128.h"
 #include "logging.h"
 #include "mem_map.h"
 #include "mutex.h"
 #include "stringpiece.h"
-#include "strutil.h"
 #include "utils.h"
 
 namespace art {
 
-union JValue;
-class String;
-class Method;
-
 // TODO: move all of the macro functionality into the DexCache class.
 class DexFile {
  public:
@@ -34,30 +28,11 @@
   // name of the DexFile entry within a zip archive
   static const char* kClassesDex;
 
-  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
-  };
+  // The value of an invalid index.
+  static const uint16_t kDexNoIndex16 = 0xFFFF;
 
   // Raw header_item.
   struct Header {
@@ -67,23 +42,23 @@
     uint32_t file_size_;  // length of entire file
     uint32_t header_size_;  // offset to start of next section
     uint32_t endian_tag_;
-    uint32_t link_size_;
-    uint32_t link_off_;
-    uint32_t map_off_;
-    uint32_t string_ids_size_;
-    uint32_t string_ids_off_;
-    uint32_t type_ids_size_;
-    uint32_t type_ids_off_;
-    uint32_t proto_ids_size_;
-    uint32_t proto_ids_off_;
-    uint32_t field_ids_size_;
-    uint32_t field_ids_off_;
-    uint32_t method_ids_size_;
-    uint32_t method_ids_off_;
-    uint32_t class_defs_size_;
-    uint32_t class_defs_off_;
-    uint32_t data_size_;
-    uint32_t data_off_;
+    uint32_t link_size_;  // unused
+    uint32_t link_off_;  // unused
+    uint32_t map_off_;  // unused
+    uint32_t string_ids_size_;  // number of StringIds
+    uint32_t string_ids_off_;  // file offset of StringIds array
+    uint32_t type_ids_size_;  // number of TypeIds, we don't support more than 65535
+    uint32_t type_ids_off_;  // file offset of TypeIds array
+    uint32_t proto_ids_size_;  // number of ProtoIds, we don't support more than 65535
+    uint32_t proto_ids_off_;  // file offset of ProtoIds array
+    uint32_t field_ids_size_;  // number of FieldIds
+    uint32_t field_ids_off_;  // file offset of FieldIds array
+    uint32_t method_ids_size_;  // number of MethodIds
+    uint32_t method_ids_off_;  // file offset of MethodIds array
+    uint32_t class_defs_size_;  // number of ClassDefs
+    uint32_t class_defs_off_;  // file offset of ClassDef array
+    uint32_t data_size_;  // unused
+    uint32_t data_off_;  // unused
    private:
     DISALLOW_COPY_AND_ASSIGN(Header);
   };
@@ -104,26 +79,27 @@
 
   // Raw field_id_item.
   struct FieldId {
-    uint16_t class_idx_;  // index into type_ids_ list for defining class
-    uint16_t type_idx_;  // index into type_ids_ for field type
-    uint32_t name_idx_;  // index into string_ids_ for field name
+    uint16_t class_idx_;  // index into type_ids_ array for defining class
+    uint16_t type_idx_;  // index into type_ids_ array for field type
+    uint32_t name_idx_;  // index into string_ids_ array for field name
    private:
     DISALLOW_COPY_AND_ASSIGN(FieldId);
   };
 
   // Raw method_id_item.
   struct MethodId {
-    uint16_t class_idx_;  // index into type_ids_ list for defining class
-    uint16_t proto_idx_;  // index into proto_ids_ for method prototype
-    uint32_t name_idx_;  // index into string_ids_ for method name
+    uint16_t class_idx_;  // index into type_ids_ array for defining class
+    uint16_t proto_idx_;  // index into proto_ids_ array for method prototype
+    uint32_t name_idx_;  // index into string_ids_ array for method name
    private:
     DISALLOW_COPY_AND_ASSIGN(MethodId);
   };
 
   // Raw proto_id_item.
   struct ProtoId {
-    uint32_t shorty_idx_;  // index into string_ids for shorty descriptor
-    uint32_t return_type_idx_;  // index into type_ids list for return type
+    uint32_t shorty_idx_;  // index into string_ids array for shorty descriptor
+    uint16_t return_type_idx_;  // index into type_ids array for return type
+    uint16_t pad_;             // padding = 0
     uint32_t parameters_off_;  // file offset to type_list for parameter types
    private:
     DISALLOW_COPY_AND_ASSIGN(ProtoId);
@@ -131,9 +107,11 @@
 
   // Raw class_def_item.
   struct ClassDef {
-    uint32_t class_idx_;  // index into type_ids_ for this class
+    uint16_t class_idx_;  // index into type_ids_ array for this class
+    uint16_t pad1_;  // padding = 0
     uint32_t access_flags_;
-    uint32_t superclass_idx_;  // index into type_ids_ for superclass
+    uint16_t superclass_idx_;  // index into type_ids_ array for superclass
+    uint16_t pad2_;  // padding = 0
     uint32_t interfaces_off_;  // file offset to TypeList
     uint32_t source_file_idx_;  // index into string_ids_ for source file name
     uint32_t annotations_off_;  // file offset to annotations_directory_item
@@ -168,37 +146,6 @@
     DISALLOW_COPY_AND_ASSIGN(TypeList);
   };
 
-  class ParameterIterator {  // TODO: stream
-   public:
-    ParameterIterator(const DexFile& dex_file, const ProtoId& proto_id)
-        : dex_file_(dex_file), size_(0), pos_(0) {
-      type_list_ = dex_file_.GetProtoParameters(proto_id);
-      if (type_list_ != NULL) {
-        size_ = type_list_->Size();
-      }
-    }
-    bool HasNext() const { return pos_ != size_; }
-    void Next() { ++pos_; }
-    const char* GetDescriptor() {
-      uint32_t type_idx = type_list_->GetTypeItem(pos_).type_idx_;
-      return dex_file_.dexStringByTypeIdx(type_idx);
-    }
-   private:
-    const DexFile& dex_file_;
-    const TypeList* type_list_;
-    uint32_t size_;
-    uint32_t pos_;
-    DISALLOW_IMPLICIT_CONSTRUCTORS(ParameterIterator);
-  };
-
-  ParameterIterator* GetParameterIterator(const ProtoId& proto_id) const {
-    return new ParameterIterator(*this, proto_id);
-  }
-
-  const char* GetReturnTypeDescriptor(const ProtoId& proto_id) const {
-    return dexStringByTypeIdx(proto_id.return_type_idx_);
-  }
-
   // Raw code_item.
   struct CodeItem {
     uint16_t registers_size_;
@@ -212,11 +159,6 @@
     DISALLOW_COPY_AND_ASSIGN(CodeItem);
   };
 
-  struct CatchHandlerItem {
-    uint32_t type_idx_;    // type index of the caught exception type
-    uint32_t address_;     // handler address
-  };
-
   // Raw try_item.
   struct TryItem {
     uint32_t start_addr_;
@@ -226,95 +168,6 @@
     DISALLOW_COPY_AND_ASSIGN(TryItem);
   };
 
-  class CatchHandlerIterator {
-    public:
-      CatchHandlerIterator() {
-        remaining_count_ = -1;
-        catch_all_ = false;
-      }
-
-      explicit CatchHandlerIterator(const byte* handler_data) {
-        current_data_ = handler_data;
-        remaining_count_ = DecodeSignedLeb128(&current_data_);
-
-        // If remaining_count_ is non-positive, then it is the negative of
-        // the number of catch types, and the catches are followed by a
-        // catch-all handler.
-        if (remaining_count_ <= 0) {
-          catch_all_ = true;
-          remaining_count_ = -remaining_count_;
-        } else {
-          catch_all_ = false;
-        }
-        Next();
-      }
-
-      const CatchHandlerItem& Get() const {
-        return handler_;
-      }
-
-      const byte* GetData() const {
-        return current_data_;
-      }
-
-      void Next() {
-        if (remaining_count_ > 0) {
-          handler_.type_idx_ = DecodeUnsignedLeb128(&current_data_);
-          handler_.address_  = DecodeUnsignedLeb128(&current_data_);
-          remaining_count_--;
-          return;
-        }
-
-        if (catch_all_) {
-          handler_.type_idx_ = kDexNoIndex;
-          handler_.address_  = DecodeUnsignedLeb128(&current_data_);
-          catch_all_ = false;
-          return;
-        }
-
-        // no more handler
-        remaining_count_ = -1;
-      }
-
-      bool HasNext() const {
-        return remaining_count_ == -1 && catch_all_ == false;
-      }
-
-    private:
-      CatchHandlerItem handler_;
-      const byte *current_data_;  // the current handler in dex file.
-      int32_t remaining_count_;   // number of handlers not read.
-      bool catch_all_;            // is there a handler that will catch all exceptions in case
-                                  // that all typed handler does not match.
-  };
-
-  // Partially decoded form of class_data_item.
-  struct ClassDataHeader {
-    uint32_t static_fields_size_;  // the number of static fields
-    uint32_t instance_fields_size_;  // the number of instance fields
-    uint32_t direct_methods_size_;  // the number of direct methods
-    uint32_t virtual_methods_size_;  // the number of virtual methods
-  };
-
-  // Decoded form of encoded_field.
-  struct Field {
-    uint32_t field_idx_;  // index into the field_ids list for the identity of this field
-    uint32_t access_flags_;  // access flags for the field
-    Field() {}
-   private:
-    DISALLOW_COPY_AND_ASSIGN(Field);
-  };
-
-  // Decoded form of encoded_method.
-  struct Method {
-    uint32_t method_idx_;
-    uint32_t access_flags_;
-    uint32_t code_off_;
-    Method() {}
-   private:
-    DISALLOW_COPY_AND_ASSIGN(Method);
-  };
-
   typedef std::pair<const DexFile*, const DexFile::ClassDef*> ClassPathEntry;
   typedef std::vector<const DexFile*> ClassPath;
 
@@ -347,82 +200,104 @@
     return *header_;
   }
 
-  // Looks up a class definition index by its class descriptor.
-  bool FindClassDefIndex(const StringPiece& descriptor, uint32_t& idx) const;
-
+  // Decode the dex magic version
   uint32_t GetVersion() const;
 
-  // Looks up a class definition by its class descriptor.
-  const ClassDef* FindClassDef(const StringPiece& descriptor) const;
-
   // Returns the number of string identifiers in the .dex file.
   size_t NumStringIds() const {
     CHECK(header_ != NULL);
     return header_->string_ids_size_;
   }
 
+  // Returns the StringId at the specified index.
+  const StringId& GetStringId(uint32_t idx) const {
+    CHECK_LT(idx, NumStringIds());
+    return string_ids_[idx];
+  }
+
+  uint32_t GetIndexForStringId(const StringId& string_id) const {
+    CHECK_GE(&string_id, string_ids_);
+    CHECK_LT(&string_id, string_ids_ + header_->string_ids_size_);
+    return &string_id - string_ids_;
+  }
+
+  int32_t GetStringLength(const StringId& string_id) const;
+
+  // Returns a pointer to the UTF-8 string data referred to by the given string_id.
+  const char* GetStringDataAndLength(const StringId& string_id, int32_t* length) const;
+
+  const char* GetStringData(const StringId& string_id) const {
+    int32_t length;
+    return GetStringDataAndLength(string_id, &length);
+  }
+
+  // return the UTF-8 encoded string with the specified string_id index
+  const char* StringDataAndLengthByIdx(uint32_t idx, int32_t* unicode_length) const {
+    if (idx == kDexNoIndex) {
+      *unicode_length = 0;
+      return NULL;
+    }
+    const StringId& string_id = GetStringId(idx);
+    return GetStringDataAndLength(string_id, unicode_length);
+  }
+
+  const char* StringDataByIdx(uint32_t idx) const {
+    int32_t unicode_length;
+    return StringDataAndLengthByIdx(idx, &unicode_length);
+  }
+
+  // Looks up a string id for a given string
+  const StringId* FindStringId(const std::string& string) const;
+
   // Returns the number of type identifiers in the .dex file.
   size_t NumTypeIds() const {
     CHECK(header_ != NULL);
     return header_->type_ids_size_;
   }
 
-  // Returns the number of prototype identifiers in the .dex file.
-  size_t NumProtoIds() const {
-    CHECK(header_ != NULL);
-    return header_->proto_ids_size_;
+  // Returns the TypeId at the specified index.
+  const TypeId& GetTypeId(uint32_t idx) const {
+    CHECK_LT(idx, NumTypeIds());
+    return type_ids_[idx];
   }
 
+  uint16_t GetIndexForTypeId(const TypeId& type_id) const {
+    CHECK_GE(&type_id, type_ids_);
+    CHECK_LT(&type_id, type_ids_ + header_->type_ids_size_);
+    size_t result = &type_id - type_ids_;
+    DCHECK(result < 65536);
+    return static_cast<uint16_t>(result);
+  }
+
+  // Get the descriptor string associated with a given type index.
+  const char* StringByTypeIdx(uint32_t idx, int32_t* unicode_length) const {
+    const TypeId& type_id = GetTypeId(idx);
+    return StringDataAndLengthByIdx(type_id.descriptor_idx_, unicode_length);
+  }
+
+  const char* StringByTypeIdx(uint32_t idx) const {
+    const TypeId& type_id = GetTypeId(idx);
+    return StringDataByIdx(type_id.descriptor_idx_);
+  }
+
+  // Returns the type descriptor string of a type id.
+  const char* GetTypeDescriptor(const TypeId& type_id) const {
+    return StringDataByIdx(type_id.descriptor_idx_);
+  }
+
+  // Looks up a type for the given string index
+  const TypeId* FindTypeId(uint32_t string_idx) const;
+
   // Returns the number of field identifiers in the .dex file.
   size_t NumFieldIds() const {
     CHECK(header_ != NULL);
     return header_->field_ids_size_;
   }
 
-  // Returns the number of method identifiers in the .dex file.
-  size_t NumMethodIds() const {
-    CHECK(header_ != NULL);
-    return header_->method_ids_size_;
-  }
-
-  // Returns the number of class definitions in the .dex file.
-  size_t NumClassDefs() const {
-    CHECK(header_ != NULL);
-    return header_->class_defs_size_;
-  }
-
-  // Returns a pointer to the memory mapped class data.
-  // TODO: return a stream
-  const byte* GetClassData(const ClassDef& class_def) const {
-    if (class_def.class_data_off_ == 0) {
-      return NULL;
-    } else {
-      return base_ + class_def.class_data_off_;
-    }
-  }
-
-  // Decodes the header section from the class data bytes.
-  ClassDataHeader ReadClassDataHeader(const byte** class_data) const {
-    CHECK(class_data != NULL);
-    ClassDataHeader header;
-    memset(&header, 0, sizeof(ClassDataHeader));
-    if (*class_data != NULL) {
-      header.static_fields_size_ = DecodeUnsignedLeb128(class_data);
-      header.instance_fields_size_ = DecodeUnsignedLeb128(class_data);
-      header.direct_methods_size_ = DecodeUnsignedLeb128(class_data);
-      header.virtual_methods_size_ = DecodeUnsignedLeb128(class_data);
-    }
-    return header;
-  }
-
-  // Returns the class descriptor string of a class definition.
-  const char* GetClassDescriptor(const ClassDef& class_def) const {
-    return dexStringByTypeIdx(class_def.class_idx_);
-  }
-
-  // Returns the type descriptor string of a type id.
-  const char* GetTypeDescriptor(const TypeId& type_id) const {
-    return dexStringById(type_id.descriptor_idx_);
+  // Returns the FieldId at the specified index.
+  const FieldId& GetFieldId(uint32_t idx) const {
+    CHECK_LT(idx, NumFieldIds());
+    return field_ids_[idx];
   }
 
   // Returns the declaring class descriptor string of a field id.
@@ -439,9 +314,31 @@
 
   // Returns the name of a field id.
   const char* GetFieldName(const FieldId& field_id) const {
-    return dexStringById(field_id.name_idx_);
+    return StringDataByIdx(field_id.name_idx_);
   }
 
+  // Returns the number of method identifiers in the .dex file.
+  size_t NumMethodIds() const {
+    CHECK(header_ != NULL);
+    return header_->method_ids_size_;
+  }
+
+  // Returns the MethodId at the specified index.
+  const MethodId& GetMethodId(uint32_t idx) const {
+    CHECK_LT(idx, NumMethodIds());
+    return method_ids_[idx];
+  }
+
+  uint32_t GetIndexForMethodId(const MethodId& method_id) const {
+    CHECK_GE(&method_id, method_ids_);
+    CHECK_LT(&method_id, method_ids_ + header_->method_ids_size_);
+    return &method_id - method_ids_;
+  }
+
+  // Looks up a method by its class_dex, name and proto_id
+  const MethodId* FindMethodId(const DexFile::TypeId& klass, const DexFile::StringId& name,
+                               const DexFile::ProtoId& signature) const;
+
   // Returns the declaring class descriptor string of a method id.
   const char* GetMethodDeclaringClassDescriptor(const MethodId& method_id) const {
     const DexFile::TypeId& type_id = GetTypeId(method_id.class_idx_);
@@ -455,42 +352,23 @@
 
   // Returns the signature of a method id.
   const std::string GetMethodSignature(const MethodId& method_id) const {
-    return CreateMethodDescriptor(method_id.proto_idx_, NULL);
+    return CreateMethodSignature(method_id.proto_idx_, NULL);
   }
 
   // Returns the name of a method id.
   const char* GetMethodName(const MethodId& method_id) const {
-    return dexStringById(method_id.name_idx_);
+    return StringDataByIdx(method_id.name_idx_);
   }
 
-  // Returns the StringId at the specified index.
-  const StringId& GetStringId(uint32_t idx) const {
-    CHECK_LT(idx, NumStringIds());
-    return string_ids_[idx];
+  // Returns the shorty of a method id.
+  const char* GetMethodShorty(const MethodId& method_id) const {
+    return StringDataByIdx(GetProtoId(method_id.proto_idx_).shorty_idx_);
   }
 
-  // Returns the TypeId at the specified index.
-  const TypeId& GetTypeId(uint32_t idx) const {
-    CHECK_LT(idx, NumTypeIds());
-    return type_ids_[idx];
-  }
-
-  // Returns the FieldId at the specified index.
-  const FieldId& GetFieldId(uint32_t idx) const {
-    CHECK_LT(idx, NumFieldIds());
-    return field_ids_[idx];
-  }
-
-  // Returns the MethodId at the specified index.
-  const MethodId& GetMethodId(uint32_t idx) const {
-    CHECK_LT(idx, NumMethodIds());
-    return method_ids_[idx];
-  }
-
-  // Returns the ProtoId at the specified index.
-  const ProtoId& GetProtoId(uint32_t idx) const {
-    CHECK_LT(idx, NumProtoIds());
-    return proto_ids_[idx];
+  // Returns the number of class definitions in the .dex file.
+  size_t NumClassDefs() const {
+    CHECK(header_ != NULL);
+    return header_->class_defs_size_;
   }
 
   // Returns the ClassDef at the specified index.
@@ -499,6 +377,23 @@
     return class_defs_[idx];
   }
 
+  uint32_t GetIndexForClassDef(const ClassDef& class_def) const {
+    CHECK_GE(&class_def, class_defs_);
+    CHECK_LT(&class_def, class_defs_ + header_->class_defs_size_);
+    return &class_def - class_defs_;
+  }
+
+  // Returns the class descriptor string of a class definition.
+  const char* GetClassDescriptor(const ClassDef& class_def) const {
+    return StringByTypeIdx(class_def.class_idx_);
+  }
+
+  // Looks up a class definition by its class descriptor.
+  const ClassDef* FindClassDef(const StringPiece& descriptor) const;
+
+  // Looks up a class definition index by its class descriptor.
+  bool FindClassDefIndex(const StringPiece& descriptor, uint32_t& idx) const;
+
   const TypeList* GetInterfacesList(const ClassDef& class_def) const {
     if (class_def.interfaces_off_ == 0) {
         return NULL;
@@ -508,10 +403,16 @@
     }
   }
 
-  const CodeItem* GetCodeItem(const Method& method) const {
-    return GetCodeItem(method.code_off_);
+  // Returns a pointer to the raw memory mapped class_data_item
+  const byte* GetClassData(const ClassDef& class_def) const {
+    if (class_def.class_data_off_ == 0) {
+      return NULL;
+    } else {
+      return base_ + class_def.class_data_off_;
+    }
   }
 
+  //
   const CodeItem* GetCodeItem(const uint32_t code_off_) const {
     if (code_off_ == 0) {
       return NULL;  // native or abstract method
@@ -521,10 +422,43 @@
     }
   }
 
+  const char* GetReturnTypeDescriptor(const ProtoId& proto_id) const {
+    return StringByTypeIdx(proto_id.return_type_idx_);
+  }
+
+  // Returns the number of prototype identifiers in the .dex file.
+  size_t NumProtoIds() const {
+    CHECK(header_ != NULL);
+    return header_->proto_ids_size_;
+  }
+
+  // Returns the ProtoId at the specified index.
+  const ProtoId& GetProtoId(uint32_t idx) const {
+    CHECK_LT(idx, NumProtoIds());
+    return proto_ids_[idx];
+  }
+
+  uint16_t GetIndexForProtoId(const ProtoId& proto_id) const {
+    CHECK_GE(&proto_id, proto_ids_);
+    CHECK_LT(&proto_id, proto_ids_ + header_->proto_ids_size_);
+    return &proto_id - proto_ids_;
+  }
+
+  // Looks up a proto id for a given return type and signature type list
+  const ProtoId* FindProtoId(uint16_t return_type_id,
+                             const std::vector<uint16_t>& signature_type_ids_) const;
+
+  // Given a signature place the type ids into the given vector, returns true on success
+  bool CreateTypeList(uint16_t* return_type_idx, std::vector<uint16_t>* param_type_idxs,
+                      const std::string& signature) const;
+
+  // Given a proto_idx decode the type list and return type into a method signature
+  std::string CreateMethodSignature(uint32_t proto_idx, int32_t* unicode_length) const;
+
   // Returns the short form method descriptor for the given prototype.
   const char* GetShorty(uint32_t proto_idx) const {
     const ProtoId& proto_id = GetProtoId(proto_idx);
-    return dexStringById(proto_id.shorty_idx_);
+    return StringDataByIdx(proto_id.shorty_idx_);
   }
 
   const TypeList* GetProtoParameters(const ProtoId& proto_id) const {
@@ -536,9 +470,7 @@
     }
   }
 
-  std::string CreateMethodDescriptor(uint32_t proto_idx, int32_t* unicode_length) const;
-
-  const byte* GetEncodedArray(const ClassDef& class_def) const {
+  const byte* GetEncodedStaticFieldValuesArray(const ClassDef& class_def) const {
     if (class_def.static_values_off_ == 0) {
       return 0;
     } else {
@@ -546,158 +478,27 @@
     }
   }
 
-  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) const;
-
-  // From libdex...
-
-  // Returns a pointer to the UTF-8 string data referred to by the
-  // given string_id.
-  const char* GetStringData(const StringId& string_id, int32_t* length) const {
-    CHECK(length != NULL);
-    const byte* ptr = base_ + string_id.string_data_off_;
-    *length = DecodeUnsignedLeb128(&ptr);
-    return reinterpret_cast<const char*>(ptr);
-  }
-
-  const char* GetStringData(const StringId& string_id) const {
-    int32_t length;
-    return GetStringData(string_id, &length);
-  }
-
-  // return the UTF-8 encoded string with the specified string_id index
-  const char* dexStringById(uint32_t idx, int32_t* unicode_length) const {
-    if (idx == kDexNoIndex) {
-      *unicode_length = 0;
-      return NULL;
-    }
-    const StringId& string_id = GetStringId(idx);
-    return GetStringData(string_id, unicode_length);
-  }
-
-  const char* dexStringById(uint32_t idx) const {
-    int32_t unicode_length;
-    return dexStringById(idx, &unicode_length);
-  }
-
-  // Get the descriptor string associated with a given type index.
-  const char* dexStringByTypeIdx(uint32_t idx, int32_t* unicode_length) const {
-    const TypeId& type_id = GetTypeId(idx);
-    return dexStringById(type_id.descriptor_idx_, unicode_length);
-  }
-
-  const char* dexStringByTypeIdx(uint32_t idx) const {
-    const TypeId& type_id = GetTypeId(idx);
-    return dexStringById(type_id.descriptor_idx_);
-  }
-
-  // TODO: encoded_field is actually a stream of bytes
-  void dexReadClassDataField(const byte** encoded_field,
-                             DexFile::Field* field,
-                             uint32_t* last_idx) const {
-    uint32_t idx = *last_idx + DecodeUnsignedLeb128(encoded_field);
-    field->access_flags_ = DecodeUnsignedLeb128(encoded_field);
-    field->field_idx_ = idx;
-    *last_idx = idx;
-  }
-
-  // TODO: encoded_method is actually a stream of bytes
-  void dexReadClassDataMethod(const byte** encoded_method,
-                              DexFile::Method* method,
-                              uint32_t* last_idx) const {
-    uint32_t idx = *last_idx + DecodeUnsignedLeb128(encoded_method);
-    method->access_flags_ = DecodeUnsignedLeb128(encoded_method);
-    method->code_off_ = DecodeUnsignedLeb128(encoded_method);
-    method->method_idx_ = idx;
-    *last_idx = idx;
-  }
-
-  static const TryItem* dexGetTryItems(const CodeItem& code_item, uint32_t offset) {
+  static const TryItem* GetTryItems(const CodeItem& code_item, uint32_t offset) {
     const uint16_t* insns_end_ = &code_item.insns_[code_item.insns_size_in_code_units_];
     return reinterpret_cast<const TryItem*>
         (RoundUp(reinterpret_cast<uint32_t>(insns_end_), 4)) + offset;
   }
 
   // Get the base of the encoded data for the given DexCode.
-  static const byte* dexGetCatchHandlerData(const CodeItem& code_item, uint32_t offset) {
-    const byte* handler_data = reinterpret_cast<const byte*>
-        (dexGetTryItems(code_item, code_item.tries_size_));
+  static const byte* GetCatchHandlerData(const CodeItem& code_item, uint32_t offset) {
+    const byte* handler_data =
+        reinterpret_cast<const byte*>(GetTryItems(code_item, code_item.tries_size_));
     return handler_data + offset;
   }
 
   // Find the handler associated with a given address, if any.
   // Initializes the given iterator and returns true if a match is
   // found. Returns end if there is no applicable handler.
-  static CatchHandlerIterator dexFindCatchHandler(const CodeItem& code_item, uint32_t address) {
-    CatchHandlerItem handler;
-    handler.address_ = -1;
-    int32_t offset = -1;
-
-    // Short-circuit the overwhelmingly common cases.
-    switch (code_item.tries_size_) {
-      case 0:
-        break;
-      case 1: {
-        const TryItem* tries = dexGetTryItems(code_item, 0);
-        uint32_t start = tries->start_addr_;
-        if (address < start)
-          break;
-
-        uint32_t end = start + tries->insn_count_;
-        if (address >= end)
-          break;
-
-        offset = tries->handler_off_;
-        break;
-      }
-      default:
-        offset = dexFindCatchHandlerOffset0(code_item, code_item.tries_size_, address);
-    }
-
-    if (offset >= 0) {
-      const byte* handler_data = dexGetCatchHandlerData(code_item, offset);
-      return CatchHandlerIterator(handler_data);
-    }
-    return CatchHandlerIterator();
-  }
-
-  static int32_t dexFindCatchHandlerOffset0(const CodeItem &code_item,
-                                            int32_t tries_size,
-                                            uint32_t address) {
-    // Note: Signed type is important for max and min.
-    int32_t min = 0;
-    int32_t max = tries_size - 1;
-
-    while (max >= min) {
-      int32_t guess = (min + max) >> 1;
-      const TryItem* pTry = dexGetTryItems(code_item, guess);
-      uint32_t start = pTry->start_addr_;
-
-      if (address < start) {
-        max = guess - 1;
-        continue;
-      }
-
-      uint32_t end = start + pTry->insn_count_;
-      if (address >= end) {
-        min = guess + 1;
-        continue;
-      }
-
-      // We have a winner!
-      return (int32_t) pTry->handler_off_;
-    }
-
-    // No match.
-    return -1;
-  }
+  static int32_t FindCatchHandlerOffset(const CodeItem &code_item, int32_t tries_size,
+                                        uint32_t address);
 
   // Get the pointer to the start of the debugging data
-  const byte* dexGetDebugInfoStream(const CodeItem* code_item) const {
+  const byte* GetDebugInfoStream(const CodeItem* code_item) const {
     if (code_item->debug_info_off_ == 0) {
       return NULL;
     } else {
@@ -718,22 +519,7 @@
                                      const char* descriptor,
                                      const char* signature);
 
-  static bool LineNumForPcCb(void* cnxt, uint32_t address, uint32_t line_num) {
-    LineNumFromPcContext* context = (LineNumFromPcContext*) cnxt;
-
-    // We know that this callback will be called in
-    // ascending address order, so keep going until we find
-    // a match or we've just gone past it.
-    if (address > context->address_) {
-      // The line number from the previous positions callback
-      // wil be the final result.
-      return true;
-    } else {
-      context->line_num_ = line_num;
-      return address == context->address_;
-    }
-  }
-
+  static bool LineNumForPcCb(void* cnxt, uint32_t address, uint32_t line_num);
 
   // Debug info opcodes and constants
   enum {
@@ -753,22 +539,14 @@
   };
 
   struct LocalInfo {
-    LocalInfo() : name_(NULL), start_address_(0), is_live_(false) {}
+    LocalInfo() : name_(NULL), descriptor_(NULL), signature_(NULL), start_address_(0),
+        is_live_(false) {}
 
-    // E.g., list
-    const char* name_;
-
-    // E.g., Ljava/util/LinkedList;
-    const char* descriptor_;
-
-    // E.g., java.util.LinkedList<java.lang.Integer>
-    const char* signature_;
-
-    // PC location where the local is first defined.
-    uint16_t start_address_;
-
-    // Is the local defined and live.
-    bool is_live_;
+    const char* name_;  // E.g., list
+    const char* descriptor_;  // E.g., Ljava/util/LinkedList;
+    const char* signature_;  // E.g., java.util.LinkedList<java.lang.Integer>
+    uint16_t start_address_;  // PC location where the local is first defined.
+    bool is_live_;  // Is the local defined and live.
 
    private:
     DISALLOW_COPY_AND_ASSIGN(LocalInfo);
@@ -800,38 +578,21 @@
   // Returns -2 for native methods (as expected in exception traces).
   //
   // This is used by runtime; therefore use art::Method not art::DexFile::Method.
-  int32_t GetLineNumFromPC(const art::Method* method, uint32_t rel_pc) const;
+  int32_t GetLineNumFromPC(const Method* method, uint32_t rel_pc) const;
 
-  void dexDecodeDebugInfo0(const CodeItem* code_item, const art::Method* method,
-                           DexDebugNewPositionCb posCb, DexDebugNewLocalCb local_cb,
-                           void* cnxt, const byte* stream, LocalInfo* local_in_reg) const;
+  void DecodeDebugInfo0(const CodeItem* code_item, const Method* method,
+                        DexDebugNewPositionCb posCb, DexDebugNewLocalCb local_cb,
+                        void* cnxt, const byte* stream, LocalInfo* local_in_reg) const;
 
-  void dexDecodeDebugInfo(const CodeItem* code_item, const art::Method* method,
-                          DexDebugNewPositionCb posCb, DexDebugNewLocalCb local_cb,
-                          void* cnxt) const {
-    const byte* stream = dexGetDebugInfoStream(code_item);
-    LocalInfo local_in_reg[code_item->registers_size_];
+  void DecodeDebugInfo(const CodeItem* code_item, const Method* method,
+                       DexDebugNewPositionCb posCb, DexDebugNewLocalCb local_cb,
+                       void* cnxt) const;
 
-    if (stream != NULL) {
-      dexDecodeDebugInfo0(code_item, method, posCb, local_cb, cnxt, stream, local_in_reg);
-    }
-    for (int reg = 0; reg < code_item->registers_size_; reg++) {
-      InvokeLocalCbIfLive(cnxt, reg, code_item->insns_size_in_code_units_, local_in_reg, local_cb);
-    }
-  }
-
-  // TODO: const reference
-  uint32_t dexGetIndexForClassDef(const ClassDef* class_def) const {
-    CHECK_GE(class_def, class_defs_);
-    CHECK_LT(class_def, class_defs_ + header_->class_defs_size_);
-    return class_def - class_defs_;
-  }
-
-  const char* dexGetSourceFile(const ClassDef& class_def) const {
+  const char* GetSourceFile(const ClassDef& class_def) const {
     if (class_def.source_file_idx_ == 0xffffffff) {
       return NULL;
     } else {
-      return dexStringById(class_def.source_file_idx_);
+      return StringDataByIdx(class_def.source_file_idx_);
     }
   }
 
@@ -889,6 +650,8 @@
   bool IsMagicValid();
 
   // The index of descriptors to class definition indexes.
+  // TODO: given type_ids are sorted by string_id index, and string_ids are alphabetically, class
+  //   lookup can be done with a binary search. Is the index necessary?
   typedef std::map<const StringPiece, uint32_t> Index;
   Index index_;
 
@@ -933,6 +696,261 @@
   const ClassDef* class_defs_;
 };
 
+// Iterate over a dex file's ProtoId's paramters
+class DexFileParameterIterator {
+ public:
+  DexFileParameterIterator(const DexFile& dex_file, const DexFile::ProtoId& proto_id)
+      : dex_file_(dex_file), size_(0), pos_(0) {
+    type_list_ = dex_file_.GetProtoParameters(proto_id);
+    if (type_list_ != NULL) {
+      size_ = type_list_->Size();
+    }
+  }
+  bool HasNext() const { return pos_ < size_; }
+  void Next() { ++pos_; }
+  uint16_t GetTypeId() {
+    return type_list_->GetTypeItem(pos_).type_idx_;
+  }
+  const char* GetDescriptor() {
+    return dex_file_.StringByTypeIdx(GetTypeId());
+  }
+ private:
+  const DexFile& dex_file_;
+  const DexFile::TypeList* type_list_;
+  uint32_t size_;
+  uint32_t pos_;
+  DISALLOW_IMPLICIT_CONSTRUCTORS(DexFileParameterIterator);
+};
+
+// Iterate and decode class_data_item
+class ClassDataItemIterator {
+ public:
+  ClassDataItemIterator(const DexFile& dex_file, const byte* raw_class_data_item)
+      : dex_file_(dex_file), pos_(0), ptr_pos_(raw_class_data_item), last_idx_(0) {
+    ReadClassDataHeader();
+    if (EndOfInstanceFieldsPos() > 0) {
+      ReadClassDataField();
+    } else if (EndOfVirtualMethodsPos() > 0) {
+      ReadClassDataMethod();
+    }
+  }
+  uint32_t NumStaticFields() const {
+    return header_.static_fields_size_;
+  }
+  uint32_t NumInstanceFields() const {
+    return header_.instance_fields_size_;
+  }
+  uint32_t NumDirectMethods() const {
+    return header_.direct_methods_size_;
+  }
+  uint32_t NumVirtualMethods() const {
+    return header_.virtual_methods_size_;
+  }
+  bool HasNextStaticField() const {
+    return pos_ < EndOfStaticFieldsPos();
+  }
+  bool HasNextInstanceField() const {
+    return pos_ >= EndOfStaticFieldsPos() && pos_ < EndOfInstanceFieldsPos();
+  }
+  bool HasNextDirectMethod() const {
+    return pos_ >= EndOfInstanceFieldsPos() && pos_ < EndOfDirectMethodsPos();
+  }
+  bool HasNextVirtualMethod() const {
+    return pos_ >= EndOfDirectMethodsPos() && pos_ < EndOfVirtualMethodsPos();
+  }
+  bool HasNext() const {
+    return pos_ < EndOfVirtualMethodsPos();
+  }
+  void Next() {
+    pos_++;
+    if (pos_ < EndOfStaticFieldsPos()) {
+      last_idx_ = GetMemberIndex();
+      ReadClassDataField();
+    } else if (pos_ == EndOfStaticFieldsPos() && NumInstanceFields() > 0) {
+      last_idx_ = 0;  // transition to next array, reset last index
+      ReadClassDataField();
+    } else if (pos_ < EndOfInstanceFieldsPos()) {
+      last_idx_ = GetMemberIndex();
+      ReadClassDataField();
+    } else if (pos_ == EndOfInstanceFieldsPos() && NumDirectMethods() > 0) {
+      last_idx_ = 0;  // transition to next array, reset last index
+      ReadClassDataMethod();
+    } else if (pos_ < EndOfDirectMethodsPos()) {
+      last_idx_ = GetMemberIndex();
+      ReadClassDataMethod();
+    } else if (pos_ == EndOfDirectMethodsPos() && NumVirtualMethods() > 0) {
+      last_idx_ = 0;  // transition to next array, reset last index
+      ReadClassDataMethod();
+    } else if (pos_ < EndOfVirtualMethodsPos()) {
+      last_idx_ = GetMemberIndex();
+      ReadClassDataMethod();
+    } else {
+      DCHECK(!HasNext());
+    }
+  }
+  uint32_t GetMemberIndex() const {
+    if (pos_ < EndOfInstanceFieldsPos()) {
+      return last_idx_ + field_.field_idx_delta_;
+    } else {
+      CHECK_LT(pos_, EndOfVirtualMethodsPos());
+      return last_idx_ + method_.method_idx_delta_;
+    }
+  }
+  uint32_t GetMemberAccessFlags() const {
+    if (pos_ < EndOfInstanceFieldsPos()) {
+      return field_.access_flags_;
+    } else {
+      CHECK_LT(pos_, EndOfVirtualMethodsPos());
+      return method_.access_flags_;
+    }
+  }
+  const DexFile::CodeItem* GetMethodCodeItem() const {
+    return dex_file_.GetCodeItem(method_.code_off_);
+  }
+  uint32_t GetMethodCodeItemOffset() const {
+    return method_.code_off_;
+  }
+ private:
+  // A dex file's class_data_item is leb128 encoded, this structure holds a decoded form of the
+  // header for a class_data_item
+  struct ClassDataHeader {
+    uint32_t static_fields_size_;  // the number of static fields
+    uint32_t instance_fields_size_;  // the number of instance fields
+    uint32_t direct_methods_size_;  // the number of direct methods
+    uint32_t virtual_methods_size_;  // the number of virtual methods
+  } header_;
+
+  // Read and decode header from a class_data_item stream into header
+  void ReadClassDataHeader();
+
+  uint32_t EndOfStaticFieldsPos() const {
+    return header_.static_fields_size_;
+  }
+  uint32_t EndOfInstanceFieldsPos() const {
+    return EndOfStaticFieldsPos() + header_.instance_fields_size_;
+  }
+  uint32_t EndOfDirectMethodsPos() const {
+    return EndOfInstanceFieldsPos() + header_.direct_methods_size_;
+  }
+  uint32_t EndOfVirtualMethodsPos() const {
+    return EndOfDirectMethodsPos() + header_.virtual_methods_size_;
+  }
+
+  // A decoded version of the field of a class_data_item
+  struct ClassDataField {
+    uint32_t field_idx_delta_;  // delta of index into the field_ids array for FieldId
+    uint32_t access_flags_;  // access flags for the field
+    ClassDataField() :  field_idx_delta_(0), access_flags_(0) {}
+   private:
+    DISALLOW_COPY_AND_ASSIGN(ClassDataField);
+  } field_;
+
+  // Read and decode a field from a class_data_item stream into field
+  void ReadClassDataField();
+
+  // A decoded version of the method of a class_data_item
+  struct ClassDataMethod {
+    uint32_t method_idx_delta_;  // delta of index into the method_ids array for MethodId
+    uint32_t access_flags_;
+    uint32_t code_off_;
+    ClassDataMethod() : method_idx_delta_(0), access_flags_(0), code_off_(0) {}
+   private:
+    DISALLOW_COPY_AND_ASSIGN(ClassDataMethod);
+  } method_;
+
+  // Read and decode a method from a class_data_item stream into method
+  void ReadClassDataMethod();
+
+  const DexFile& dex_file_;
+  size_t pos_;  // integral number of items passed
+  const byte* ptr_pos_;  // pointer into stream of class_data_item
+  uint32_t last_idx_;  // last read field or method index to apply delta to
+  DISALLOW_IMPLICIT_CONSTRUCTORS(ClassDataItemIterator);
+};
+
+class ClassLinker;
+class DexCache;
+class Field;
+
+class EncodedStaticFieldValueIterator {
+ public:
+  EncodedStaticFieldValueIterator(const DexFile& dex_file, DexCache* dex_cache,
+                                  ClassLinker* linker, const DexFile::ClassDef& class_def);
+
+  void ReadValueToField(Field* field) const;
+
+  bool HasNext() { return pos_ < array_size_; }
+
+  void Next();
+ private:
+  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
+  };
+
+  static const byte kEncodedValueTypeMask = 0x1f;  // 0b11111
+  static const byte kEncodedValueArgShift = 5;
+
+  const DexFile& dex_file_;
+  DexCache* dex_cache_;  // dex cache to resolve literal objects
+  ClassLinker* linker_;  // linker to resolve literal objects
+  size_t array_size_;  // size of array
+  size_t pos_;  // current position
+  const byte* ptr_;  // pointer into encoded data array
+  byte type_;  // type of current encoded value
+  jvalue jval_;  // value of current encoded value
+  DISALLOW_IMPLICIT_CONSTRUCTORS(EncodedStaticFieldValueIterator);
+};
+
+class CatchHandlerIterator {
+  public:
+    CatchHandlerIterator(const DexFile::CodeItem& code_item, uint32_t address);
+    explicit CatchHandlerIterator(const byte* handler_data) {
+      Init(handler_data);
+    }
+
+    uint16_t GetHandlerTypeIndex() const {
+      return handler_.type_idx_;
+    }
+    uint32_t GetHandlerAddress() const {
+      return handler_.address_;
+    }
+    void Next();
+    bool HasNext() const {
+      return remaining_count_ != -1 || catch_all_;
+    }
+    // End of this set of catch blocks, convenience method to locate next set of catch blocks
+    const byte* EndDataPointer() const {
+      CHECK(!HasNext());
+      return current_data_;
+    }
+  private:
+    void Init(const byte* handler_data);
+
+    struct CatchHandlerItem {
+      uint16_t type_idx_;  // type index of the caught exception type
+      uint32_t address_;  // handler address
+    } handler_;
+    const byte *current_data_;  // the current handler in dex file.
+    int32_t remaining_count_;   // number of handlers not read.
+    bool catch_all_;            // is there a handler that will catch all exceptions in case
+                                // that all typed handler does not match.
+};
+
 }  // namespace art
 
 #endif  // ART_SRC_DEX_FILE_H_
diff --git a/src/dex_file_test.cc b/src/dex_file_test.cc
index e33276b..6f99551 100644
--- a/src/dex_file_test.cc
+++ b/src/dex_file_test.cc
@@ -81,65 +81,118 @@
   EXPECT_STREQ("LNested;", raw->GetClassDescriptor(c1));
 }
 
-TEST_F(DexFileTest, CreateMethodDescriptor) {
-  UniquePtr<const DexFile> raw(OpenTestDexFile("CreateMethodDescriptor"));
+TEST_F(DexFileTest, CreateMethodSignature) {
+  UniquePtr<const DexFile> raw(OpenTestDexFile("CreateMethodSignature"));
   ASSERT_TRUE(raw.get() != NULL);
   EXPECT_EQ(1U, raw->NumClassDefs());
 
   const DexFile::ClassDef& class_def = raw->GetClassDef(0);
-  ASSERT_STREQ("LCreateMethodDescriptor;", raw->GetClassDescriptor(class_def));
+  ASSERT_STREQ("LCreateMethodSignature;", raw->GetClassDescriptor(class_def));
 
   const byte* class_data = raw->GetClassData(class_def);
   ASSERT_TRUE(class_data != NULL);
-  DexFile::ClassDataHeader header = raw->ReadClassDataHeader(&class_data);
+  ClassDataItemIterator it(*raw.get(), class_data);
 
-  EXPECT_EQ(1u, header.direct_methods_size_);
+  EXPECT_EQ(1u, it.NumDirectMethods());
 
-  // Check the descriptor for the static initializer.
+  // Check the signature for the static initializer.
   {
-    uint32_t last_idx = 0;
-    ASSERT_EQ(1U, header.direct_methods_size_);
-    DexFile::Method method;
-    raw->dexReadClassDataMethod(&class_data, &method, &last_idx);
-    const DexFile::MethodId& method_id = raw->GetMethodId(method.method_idx_);
+    ASSERT_EQ(1U, it.NumDirectMethods());
+    const DexFile::MethodId& method_id = raw->GetMethodId(it.GetMemberIndex());
     uint32_t proto_idx = method_id.proto_idx_;
-    const char* name = raw->dexStringById(method_id.name_idx_);
+    const char* name = raw->StringDataByIdx(method_id.name_idx_);
     ASSERT_STREQ("<init>", name);
     int32_t length;
-    std::string descriptor(raw->CreateMethodDescriptor(proto_idx, &length));
-    ASSERT_EQ("()V", descriptor);
+    std::string signature(raw->CreateMethodSignature(proto_idx, &length));
+    ASSERT_EQ("()V", signature);
   }
 
   // Check both virtual methods.
-  ASSERT_EQ(2U, header.virtual_methods_size_);
-  uint32_t last_idx = 0;
-
+  ASSERT_EQ(2U, it.NumVirtualMethods());
   {
-    DexFile::Method method;
-    raw->dexReadClassDataMethod(&class_data, &method, &last_idx);
-    const DexFile::MethodId& method_id = raw->GetMethodId(method.method_idx_);
+    it.Next();
+    const DexFile::MethodId& method_id = raw->GetMethodId(it.GetMemberIndex());
 
-    const char* name = raw->dexStringById(method_id.name_idx_);
+    const char* name = raw->StringDataByIdx(method_id.name_idx_);
     ASSERT_STREQ("m1", name);
 
     uint32_t proto_idx = method_id.proto_idx_;
     int32_t length;
-    std::string descriptor(raw->CreateMethodDescriptor(proto_idx, &length));
-    ASSERT_EQ("(IDJLjava/lang/Object;)Ljava/lang/Float;", descriptor);
+    std::string signature(raw->CreateMethodSignature(proto_idx, &length));
+    ASSERT_EQ("(IDJLjava/lang/Object;)Ljava/lang/Float;", signature);
   }
 
   {
-    DexFile::Method method;
-    raw->dexReadClassDataMethod(&class_data, &method, &last_idx);
-    const DexFile::MethodId& method_id = raw->GetMethodId(method.method_idx_);
+    it.Next();
+    const DexFile::MethodId& method_id = raw->GetMethodId(it.GetMemberIndex());
 
-    const char* name = raw->dexStringById(method_id.name_idx_);
+    const char* name = raw->StringDataByIdx(method_id.name_idx_);
     ASSERT_STREQ("m2", name);
 
     uint32_t proto_idx = method_id.proto_idx_;
     int32_t length;
-    std::string descriptor(raw->CreateMethodDescriptor(proto_idx, &length));
-    ASSERT_EQ("(ZSC)LCreateMethodDescriptor;", descriptor);
+    std::string signature(raw->CreateMethodSignature(proto_idx, &length));
+    ASSERT_EQ("(ZSC)LCreateMethodSignature;", signature);
+  }
+}
+
+TEST_F(DexFileTest, FindStringId) {
+  UniquePtr<const DexFile> raw(OpenTestDexFile("CreateMethodSignature"));
+  ASSERT_TRUE(raw.get() != NULL);
+  EXPECT_EQ(1U, raw->NumClassDefs());
+
+  const char* strings[] = { "LCreateMethodSignature;", "Ljava/lang/Float;", "Ljava/lang/Object;",
+      "D", "I", "J", NULL };
+  for (size_t i = 0; strings[i] != NULL; i++) {
+    const char* str = strings[i];
+    const DexFile::StringId* str_id = raw->FindStringId(str);
+    const char* dex_str = raw->GetStringData(*str_id);
+    EXPECT_STREQ(dex_str, str);
+  }
+}
+
+TEST_F(DexFileTest, FindTypeId) {
+  for (size_t i = 0; i < java_lang_dex_file_->NumTypeIds(); i++) {
+    const char* type_str = java_lang_dex_file_->StringByTypeIdx(i);
+    const DexFile::StringId* type_str_id = java_lang_dex_file_->FindStringId(type_str);
+    ASSERT_TRUE(type_str_id != NULL);
+    uint32_t type_str_idx = java_lang_dex_file_->GetIndexForStringId(*type_str_id);
+    const DexFile::TypeId* type_id = java_lang_dex_file_->FindTypeId(type_str_idx);
+    ASSERT_TRUE(type_id != NULL);
+    EXPECT_EQ(java_lang_dex_file_->GetIndexForTypeId(*type_id), i);
+  }
+}
+
+TEST_F(DexFileTest, FindProtoId) {
+  for (size_t i = 0; i < java_lang_dex_file_->NumProtoIds(); i++) {
+    const DexFile::ProtoId& to_find = java_lang_dex_file_->GetProtoId(i);
+    const DexFile::TypeList* to_find_tl = java_lang_dex_file_->GetProtoParameters(to_find);
+    std::vector<uint16_t> to_find_types;
+    if (to_find_tl != NULL) {
+      for (size_t j = 0; j < to_find_tl->Size(); j++) {
+        to_find_types.push_back(to_find_tl->GetTypeItem(j).type_idx_);
+      }
+    }
+    const DexFile::ProtoId* found =
+        java_lang_dex_file_->FindProtoId(to_find.return_type_idx_, to_find_types);
+    ASSERT_TRUE(found != NULL);
+    EXPECT_EQ(java_lang_dex_file_->GetIndexForProtoId(*found), i);
+  }
+}
+
+TEST_F(DexFileTest, FindMethodId) {
+  for (size_t i = 0; i < java_lang_dex_file_->NumMethodIds(); i++) {
+    const DexFile::MethodId& to_find = java_lang_dex_file_->GetMethodId(i);
+    const DexFile::TypeId& klass = java_lang_dex_file_->GetTypeId(to_find.class_idx_);
+    const DexFile::StringId& name = java_lang_dex_file_->GetStringId(to_find.name_idx_);
+    const DexFile::ProtoId& signature = java_lang_dex_file_->GetProtoId(to_find.proto_idx_);
+    const DexFile::MethodId* found = java_lang_dex_file_->FindMethodId(klass, name, signature);
+    int32_t length;
+    ASSERT_TRUE(found != NULL) << "Didn't find method " << i << ": "
+        << java_lang_dex_file_->StringByTypeIdx(to_find.class_idx_) << "."
+        << java_lang_dex_file_->GetStringData(name)
+        << java_lang_dex_file_->CreateMethodSignature(to_find.proto_idx_, &length);
+    EXPECT_EQ(java_lang_dex_file_->GetIndexForMethodId(*found), i);
   }
 }
 
diff --git a/src/dex_verifier.cc b/src/dex_verifier.cc
index 3ad9996..d162aec 100644
--- a/src/dex_verifier.cc
+++ b/src/dex_verifier.cc
@@ -11,6 +11,7 @@
 #include "dex_instruction_visitor.h"
 #include "dex_verifier.h"
 #include "intern_table.h"
+#include "leb128.h"
 #include "logging.h"
 #include "runtime.h"
 #include "stringpiece.h"
@@ -1031,7 +1032,7 @@
     return true;
   }
   uint32_t insns_size = code_item_->insns_size_in_code_units_;
-  const DexFile::TryItem* tries = DexFile::dexGetTryItems(*code_item_, 0);
+  const DexFile::TryItem* tries = DexFile::GetTryItems(*code_item_, 0);
 
   for (uint32_t idx = 0; idx < tries_size; idx++) {
     const DexFile::TryItem* try_item = &tries[idx];
@@ -1052,14 +1053,13 @@
     }
   }
   /* Iterate over each of the handlers to verify target addresses. */
-  const byte* handlers_ptr = DexFile::dexGetCatchHandlerData(*code_item_, 0);
+  const byte* handlers_ptr = DexFile::GetCatchHandlerData(*code_item_, 0);
   uint32_t handlers_size = DecodeUnsignedLeb128(&handlers_ptr);
   ClassLinker* linker = Runtime::Current()->GetClassLinker();
   for (uint32_t idx = 0; idx < handlers_size; idx++) {
-    DexFile::CatchHandlerIterator iterator(handlers_ptr);
-    for (; !iterator.HasNext(); iterator.Next()) {
-      const DexFile::CatchHandlerItem& handler = iterator.Get();
-      uint32_t dex_pc= handler.address_;
+    CatchHandlerIterator iterator(handlers_ptr);
+    for (; iterator.HasNext(); iterator.Next()) {
+      uint32_t dex_pc= iterator.GetHandlerAddress();
       if (!insn_flags_[dex_pc].IsOpcode()) {
         Fail(VERIFY_ERROR_GENERIC) << "exception handler starts at bad address (" << dex_pc << ")";
         return false;
@@ -1067,15 +1067,15 @@
       insn_flags_[dex_pc].SetBranchTarget();
       // Ensure exception types are resolved so that they don't need resolution to be delivered,
       // unresolved exception types will be ignored by exception delivery
-      if (handler.type_idx_ != DexFile::kDexNoIndex) {
-        Class* exception_type = linker->ResolveType(handler.type_idx_, method_);
+      if (iterator.GetHandlerTypeIndex() != DexFile::kDexNoIndex16) {
+        Class* exception_type = linker->ResolveType(iterator.GetHandlerTypeIndex(), method_);
         if (exception_type == NULL) {
           DCHECK(Thread::Current()->IsExceptionPending());
           Thread::Current()->ClearException();
         }
       }
     }
-    handlers_ptr = iterator.GetData();
+    handlers_ptr = iterator.EndDataPointer();
   }
   return true;
 }
@@ -1221,7 +1221,7 @@
     return false;
   }
   // We don't need the actual class, just a pointer to the class name.
-  const char* descriptor = dex_file_->dexStringByTypeIdx(idx);
+  const char* descriptor = dex_file_->StringByTypeIdx(idx);
   if (descriptor[0] != 'L') {
     Fail(VERIFY_ERROR_GENERIC) << "can't call new-instance on type '" << descriptor << "'";
     return false;
@@ -1254,7 +1254,7 @@
     return false;
   }
   int bracket_count = 0;
-  const char* descriptor = dex_file_->dexStringByTypeIdx(idx);
+  const char* descriptor = dex_file_->StringByTypeIdx(idx);
   const char* cp = descriptor;
   while (*cp++ == '[') {
     bracket_count++;
@@ -1575,7 +1575,7 @@
   }
 
   const DexFile::ProtoId& proto_id = dex_file_->GetProtoId(method_->GetProtoIdx());
-  DexFile::ParameterIterator iterator(*dex_file_, proto_id);
+  DexFileParameterIterator iterator(*dex_file_, proto_id);
 
   for (; iterator.HasNext(); iterator.Next()) {
     const char* descriptor = iterator.GetDescriptor();
@@ -2364,7 +2364,7 @@
           uint32_t method_idx = dec_insn.vB_;
           const DexFile::MethodId& method_id = dex_file_->GetMethodId(method_idx);
           uint32_t return_type_idx = dex_file_->GetProtoId(method_id.proto_idx_).return_type_idx_;
-          descriptor =  dex_file_->dexStringByTypeIdx(return_type_idx);
+          descriptor =  dex_file_->StringByTypeIdx(return_type_idx);
         } else {
           descriptor = called_method->GetReturnTypeDescriptor();
         }
@@ -2442,7 +2442,7 @@
           uint32_t method_idx = dec_insn.vB_;
           const DexFile::MethodId& method_id = dex_file_->GetMethodId(method_idx);
           uint32_t return_type_idx = dex_file_->GetProtoId(method_id.proto_idx_).return_type_idx_;
-          descriptor =  dex_file_->dexStringByTypeIdx(return_type_idx);
+          descriptor =  dex_file_->StringByTypeIdx(return_type_idx);
         } else {
           descriptor = called_method->GetReturnTypeDescriptor();
         }
@@ -2463,7 +2463,7 @@
             uint32_t method_idx = dec_insn.vB_;
             const DexFile::MethodId& method_id = dex_file_->GetMethodId(method_idx);
             uint32_t return_type_idx = dex_file_->GetProtoId(method_id.proto_idx_).return_type_idx_;
-            descriptor =  dex_file_->dexStringByTypeIdx(return_type_idx);
+            descriptor =  dex_file_->StringByTypeIdx(return_type_idx);
           } else {
             descriptor = called_method->GetReturnTypeDescriptor();
           }
@@ -2518,7 +2518,7 @@
           uint32_t method_idx = dec_insn.vB_;
           const DexFile::MethodId& method_id = dex_file_->GetMethodId(method_idx);
           uint32_t return_type_idx = dex_file_->GetProtoId(method_id.proto_idx_).return_type_idx_;
-          descriptor =  dex_file_->dexStringByTypeIdx(return_type_idx);
+          descriptor =  dex_file_->StringByTypeIdx(return_type_idx);
         } else {
           descriptor = abs_method->GetReturnTypeDescriptor();
         }
@@ -2891,11 +2891,10 @@
    */
   if ((opcode_flag & Instruction::kThrow) != 0 && insn_flags_[work_insn_idx_].IsInTry()) {
     bool within_catch_all = false;
-    DexFile::CatchHandlerIterator iterator =
-        DexFile::dexFindCatchHandler(*code_item_, work_insn_idx_);
+    CatchHandlerIterator iterator(*code_item_, work_insn_idx_);
 
-    for (; !iterator.HasNext(); iterator.Next()) {
-      if (iterator.Get().type_idx_ == DexFile::kDexNoIndex) {
+    for (; iterator.HasNext(); iterator.Next()) {
+      if (iterator.GetHandlerTypeIndex() == DexFile::kDexNoIndex16) {
         within_catch_all = true;
       }
       /*
@@ -2903,7 +2902,7 @@
        * "work_regs", because at runtime the exception will be thrown before the instruction
        * modifies any registers.
        */
-      if (!UpdateRegisters(iterator.Get().address_, saved_line_.get())) {
+      if (!UpdateRegisters(iterator.GetHandlerAddress(), saved_line_.get())) {
         return false;
       }
     }
@@ -2953,7 +2952,7 @@
 }
 
 const RegType& DexVerifier::ResolveClassAndCheckAccess(uint32_t class_idx) {
-  const char* descriptor = dex_file_->dexStringByTypeIdx(class_idx);
+  const char* descriptor = dex_file_->StringByTypeIdx(class_idx);
   Class* referrer = method_->GetDeclaringClass();
   Class* klass = method_->GetDexCacheResolvedTypes()->Get(class_idx);
   const RegType& result =
@@ -2977,17 +2976,16 @@
 const RegType& DexVerifier::GetCaughtExceptionType() {
   const RegType* common_super = NULL;
   if (code_item_->tries_size_ != 0) {
-    const byte* handlers_ptr = DexFile::dexGetCatchHandlerData(*code_item_, 0);
+    const byte* handlers_ptr = DexFile::GetCatchHandlerData(*code_item_, 0);
     uint32_t handlers_size = DecodeUnsignedLeb128(&handlers_ptr);
     for (uint32_t i = 0; i < handlers_size; i++) {
-      DexFile::CatchHandlerIterator iterator(handlers_ptr);
-      for (; !iterator.HasNext(); iterator.Next()) {
-        DexFile::CatchHandlerItem handler = iterator.Get();
-        if (handler.address_ == (uint32_t) work_insn_idx_) {
-          if (handler.type_idx_ == DexFile::kDexNoIndex) {
+      CatchHandlerIterator iterator(handlers_ptr);
+      for (; iterator.HasNext(); iterator.Next()) {
+        if (iterator.GetHandlerAddress() == (uint32_t) work_insn_idx_) {
+          if (iterator.GetHandlerTypeIndex() == DexFile::kDexNoIndex16) {
             common_super = &reg_types_.JavaLangThrowable();
           } else {
-            const RegType& exception = ResolveClassAndCheckAccess(handler.type_idx_);
+            const RegType& exception = ResolveClassAndCheckAccess(iterator.GetHandlerTypeIndex());
             /* TODO: on error do we want to keep going?  If we don't fail this we run the risk of
              * having a non-Throwable introduced at runtime. However, that won't pass an instanceof
              * test, so is essentially harmless.
@@ -3006,7 +3004,7 @@
           }
         }
       }
-      handlers_ptr = iterator.GetData();
+      handlers_ptr = iterator.EndDataPointer();
     }
   }
   if (common_super == NULL) {
@@ -3028,7 +3026,7 @@
     }
     Class* klass = klass_type.GetClass();
     const char* name = dex_file_->GetMethodName(method_id);
-    std::string signature(dex_file_->CreateMethodDescriptor(method_id.proto_idx_, NULL));
+    std::string signature(dex_file_->CreateMethodSignature(method_id.proto_idx_, NULL));
     if (is_direct) {
       res_method = klass->FindDirectMethod(name, signature);
     } else if (klass->IsInterface()) {
diff --git a/src/exception_test.cc b/src/exception_test.cc
index df64329..559636f 100644
--- a/src/exception_test.cc
+++ b/src/exception_test.cc
@@ -67,28 +67,30 @@
   ASSERT_NE(0u, code_item->insns_size_in_code_units_);
 
   const struct DexFile::TryItem *t0, *t1;
-  t0 = dex_->dexGetTryItems(*code_item, 0);
-  t1 = dex_->dexGetTryItems(*code_item, 1);
+  t0 = dex_->GetTryItems(*code_item, 0);
+  t1 = dex_->GetTryItems(*code_item, 1);
   EXPECT_LE(t0->start_addr_, t1->start_addr_);
-
-  DexFile::CatchHandlerIterator iter =
-    dex_->dexFindCatchHandler(*code_item, 4 /* Dex PC in the first try block */);
-  ASSERT_EQ(false, iter.HasNext());
-  EXPECT_STREQ("Ljava/io/IOException;", dex_->dexStringByTypeIdx(iter.Get().type_idx_));
-  iter.Next();
-  ASSERT_EQ(false, iter.HasNext());
-  EXPECT_STREQ("Ljava/lang/Exception;", dex_->dexStringByTypeIdx(iter.Get().type_idx_));
-  iter.Next();
-  ASSERT_EQ(true, iter.HasNext());
-
-  iter = dex_->dexFindCatchHandler(*code_item, 8 /* Dex PC in the second try block */);
-  ASSERT_EQ(false, iter.HasNext());
-  EXPECT_STREQ("Ljava/io/IOException;", dex_->dexStringByTypeIdx(iter.Get().type_idx_));
-  iter.Next();
-  ASSERT_EQ(true, iter.HasNext());
-
-  iter = dex_->dexFindCatchHandler(*code_item, 11 /* Dex PC not in any try block */);
-  ASSERT_EQ(true, iter.HasNext());
+  {
+    CatchHandlerIterator iter(*code_item, 4 /* Dex PC in the first try block */);
+    EXPECT_STREQ("Ljava/io/IOException;", dex_->StringByTypeIdx(iter.GetHandlerTypeIndex()));
+    ASSERT_TRUE(iter.HasNext());
+    iter.Next();
+    EXPECT_STREQ("Ljava/lang/Exception;", dex_->StringByTypeIdx(iter.GetHandlerTypeIndex()));
+    ASSERT_TRUE(iter.HasNext());
+    iter.Next();
+    EXPECT_FALSE(iter.HasNext());
+  }
+  {
+    CatchHandlerIterator iter(*code_item, 8 /* Dex PC in the second try block */);
+    EXPECT_STREQ("Ljava/io/IOException;", dex_->StringByTypeIdx(iter.GetHandlerTypeIndex()));
+    ASSERT_TRUE(iter.HasNext());
+    iter.Next();
+    EXPECT_FALSE(iter.HasNext());
+  }
+  {
+    CatchHandlerIterator iter(*code_item, 11 /* Dex PC not in any try block */);
+    EXPECT_FALSE(iter.HasNext());
+  }
 }
 
 TEST_F(ExceptionTest, StackTraceElement) {
diff --git a/src/image_test.cc b/src/image_test.cc
index 3e64d95..88ddae9 100644
--- a/src/image_test.cc
+++ b/src/image_test.cc
@@ -21,6 +21,14 @@
   bool success_oat = OatWriter::Create(tmp_oat.GetFile(), NULL, *compiler_.get());
   ASSERT_TRUE(success_oat);
 
+  // Force all system classes into memory
+  for (size_t i = 0; i < java_lang_dex_file_->NumClassDefs(); i++) {
+    const DexFile::ClassDef& class_def = java_lang_dex_file_->GetClassDef(i);
+    const char* descriptor = java_lang_dex_file_->GetClassDescriptor(class_def);
+    Class* klass = class_linker_->FindSystemClass(descriptor);
+    EXPECT_TRUE(klass != NULL) << descriptor;
+  }
+
   ImageWriter writer;
   ScratchFile tmp_image;
   const uintptr_t requested_image_base = 0x60000000;
diff --git a/src/jni_compiler.cc b/src/jni_compiler.cc
index 127b53d..5a4056a 100644
--- a/src/jni_compiler.cc
+++ b/src/jni_compiler.cc
@@ -7,6 +7,7 @@
 
 #include "assembler.h"
 #include "calling_convention.h"
+#include "class_linker.h"
 #include "compiled_method.h"
 #include "constants.h"
 #include "jni_internal.h"
@@ -55,7 +56,12 @@
 //   registers, a reference to the method object is supplied as part of this
 //   convention.
 //
-CompiledMethod* JniCompiler::Compile(const Method* native_method) {
+CompiledMethod* JniCompiler::Compile(bool is_direct, uint32_t method_idx,
+                                     const ClassLoader* class_loader, const DexFile& dex_file) {
+  ClassLinker* linker = Runtime::Current()->GetClassLinker();
+  DexCache* dex_cache = linker->FindDexCache(dex_file);
+  Method* native_method = linker->ResolveMethod(dex_file, method_idx, dex_cache,
+                                                class_loader, is_direct);
   CHECK(native_method->IsNative());
 
   // Calling conventions used to iterate over parameters to method
@@ -435,7 +441,6 @@
   return new CompiledMethod(instruction_set_,
                             managed_code,
                             frame_size,
-                            jni_conv->ReturnPcOffset(),
                             jni_conv->CoreSpillMask(),
                             jni_conv->FpSpillMask());
 #undef __
diff --git a/src/jni_compiler.h b/src/jni_compiler.h
index a6d5602..dbdfa68 100644
--- a/src/jni_compiler.h
+++ b/src/jni_compiler.h
@@ -25,7 +25,8 @@
   explicit JniCompiler(InstructionSet instruction_set);
   ~JniCompiler();
 
-  CompiledMethod* Compile(const Method* method);
+  CompiledMethod* Compile(bool is_direct, uint32_t method_idx, const ClassLoader* class_loader,
+                          const DexFile& dex_file);
 
   // Stub to perform native method symbol lookup via dlsym
   // TODO: remove from JniCompiler
diff --git a/src/jni_internal.cc b/src/jni_internal.cc
index 5787c65..9936f25 100644
--- a/src/jni_internal.cc
+++ b/src/jni_internal.cc
@@ -101,6 +101,42 @@
   return reinterpret_cast<T>(ref);
 }
 
+size_t NumArgArrayBytes(const char* shorty) {
+  size_t num_bytes = 0;
+  size_t end = strlen(shorty);
+  for (size_t i = 1; i < end; ++i) {
+    char ch = shorty[i];
+    if (ch == 'D' || ch == 'J') {
+      num_bytes += 8;
+    } else if (ch == 'L') {
+      // Argument is a reference or an array.  The shorty descriptor
+      // does not distinguish between these types.
+      num_bytes += sizeof(Object*);
+    } else {
+      num_bytes += 4;
+    }
+  }
+  return num_bytes;
+}
+
+static size_t NumArgArrayBytes(const String* shorty) {
+  size_t num_bytes = 0;
+  size_t end = shorty->GetLength();
+  for (size_t i = 1; i < end; ++i) {
+    char ch = shorty->CharAt(i);
+    if (ch == 'D' || ch == 'J') {
+      num_bytes += 8;
+    } else if (ch == 'L') {
+      // Argument is a reference or an array.  The shorty descriptor
+      // does not distinguish between these types.
+      num_bytes += sizeof(Object*);
+    } else {
+      num_bytes += 4;
+    }
+  }
+  return num_bytes;
+}
+
 // For external use.
 template<typename T>
 T Decode(JNIEnv* public_env, jobject obj) {
@@ -139,11 +175,11 @@
   return reinterpret_cast<T>(ts.Self()->DecodeJObject(obj));
 }
 
-byte* CreateArgArray(JNIEnv* public_env, Method* method, va_list ap) {
+static byte* CreateArgArray(JNIEnv* public_env, Method* method, va_list ap) {
   JNIEnvExt* env = reinterpret_cast<JNIEnvExt*>(public_env);
-  size_t num_bytes = method->NumArgArrayBytes();
-  UniquePtr<byte[]> arg_array(new byte[num_bytes]);
   const String* shorty = method->GetShorty();
+  size_t num_bytes = NumArgArrayBytes(shorty);
+  UniquePtr<byte[]> arg_array(new byte[num_bytes]);
   for (int i = 1, offset = 0; i < shorty->GetLength(); ++i) {
     switch (shorty->CharAt(i)) {
       case 'Z':
@@ -177,9 +213,9 @@
   return arg_array.release();
 }
 
-byte* CreateArgArray(JNIEnv* public_env, Method* method, jvalue* args) {
+static byte* CreateArgArray(JNIEnv* public_env, Method* method, jvalue* args) {
   JNIEnvExt* env = reinterpret_cast<JNIEnvExt*>(public_env);
-  size_t num_bytes = method->NumArgArrayBytes();
+  size_t num_bytes = NumArgArrayBytes(method->GetShorty());
   UniquePtr<byte[]> arg_array(new byte[num_bytes]);
   const String* shorty = method->GetShorty();
   for (int i = 1, offset = 0; i < shorty->GetLength(); ++i) {
@@ -215,14 +251,14 @@
   return arg_array.release();
 }
 
-JValue InvokeWithArgArray(JNIEnv* public_env, Object* receiver, Method* method, byte* args) {
+static JValue InvokeWithArgArray(JNIEnv* public_env, Object* receiver, Method* method, byte* args) {
   JNIEnvExt* env = reinterpret_cast<JNIEnvExt*>(public_env);
   JValue result;
   method->Invoke(env->self, receiver, args, &result);
   return result;
 }
 
-JValue InvokeWithVarArgs(JNIEnv* public_env, jobject obj, jmethodID mid, va_list args) {
+static JValue InvokeWithVarArgs(JNIEnv* public_env, jobject obj, jmethodID mid, va_list args) {
   JNIEnvExt* env = reinterpret_cast<JNIEnvExt*>(public_env);
   Object* receiver = Decode<Object*>(env, obj);
   Method* method = DecodeMethod(mid);
@@ -230,11 +266,12 @@
   return InvokeWithArgArray(env, receiver, method, arg_array.get());
 }
 
-Method* FindVirtualMethod(Object* receiver, Method* method) {
+static Method* FindVirtualMethod(Object* receiver, Method* method) {
   return receiver->GetClass()->FindVirtualMethodForVirtualOrInterface(method);
 }
 
-JValue InvokeVirtualOrInterfaceWithJValues(JNIEnv* public_env, jobject obj, jmethodID mid, jvalue* args) {
+static JValue InvokeVirtualOrInterfaceWithJValues(JNIEnv* public_env, jobject obj, jmethodID mid,
+                                                  jvalue* args) {
   JNIEnvExt* env = reinterpret_cast<JNIEnvExt*>(public_env);
   Object* receiver = Decode<Object*>(env, obj);
   Method* method = FindVirtualMethod(receiver, DecodeMethod(mid));
@@ -242,7 +279,8 @@
   return InvokeWithArgArray(env, receiver, method, arg_array.get());
 }
 
-JValue InvokeVirtualOrInterfaceWithVarArgs(JNIEnv* public_env, jobject obj, jmethodID mid, va_list args) {
+static JValue InvokeVirtualOrInterfaceWithVarArgs(JNIEnv* public_env, jobject obj, jmethodID mid,
+                                                  va_list args) {
   JNIEnvExt* env = reinterpret_cast<JNIEnvExt*>(public_env);
   Object* receiver = Decode<Object*>(env, obj);
   Method* method = FindVirtualMethod(receiver, DecodeMethod(mid));
@@ -255,7 +293,7 @@
 // (i.e. "a/b/C" rather than "La/b/C;"). Arrays of reference types are an
 // exception; there the "L;" must be present ("[La/b/C;"). Historically we've
 // supported names with dots too (such as "a.b.C").
-std::string NormalizeJniClassDescriptor(const char* name) {
+static std::string NormalizeJniClassDescriptor(const char* name) {
   std::string result;
   // Add the missing "L;" if necessary.
   if (name[0] == '[') {
@@ -274,13 +312,13 @@
   return result;
 }
 
-void ThrowNoSuchMethodError(ScopedJniThreadState& ts, Class* c, const char* name, const char* sig, const char* kind) {
+static void ThrowNoSuchMethodError(ScopedJniThreadState& ts, Class* c, const char* name, const char* sig, const char* kind) {
   std::string class_descriptor(c->GetDescriptor()->ToModifiedUtf8());
   ts.Self()->ThrowNewExceptionF("Ljava/lang/NoSuchMethodError;",
       "no %s method \"%s.%s%s\"", kind, class_descriptor.c_str(), name, sig);
 }
 
-jmethodID FindMethodID(ScopedJniThreadState& ts, jclass jni_class, const char* name, const char* sig, bool is_static) {
+static jmethodID FindMethodID(ScopedJniThreadState& ts, jclass jni_class, const char* name, const char* sig, bool is_static) {
   Class* c = Decode<Class*>(ts, jni_class);
   if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(c, true)) {
     return NULL;
@@ -308,7 +346,7 @@
   return EncodeMethod(method);
 }
 
-const ClassLoader* GetClassLoader(Thread* self) {
+static const ClassLoader* GetClassLoader(Thread* self) {
   Frame frame = self->GetTopOfStack();
   Method* method = frame.GetMethod();
   if (method == NULL || PrettyMethod(method, false) == "java.lang.Runtime.nativeLoad") {
@@ -317,7 +355,7 @@
   return method->GetDeclaringClass()->GetClassLoader();
 }
 
-jfieldID FindFieldID(ScopedJniThreadState& ts, jclass jni_class, const char* name, const char* sig, bool is_static) {
+static jfieldID FindFieldID(ScopedJniThreadState& ts, jclass jni_class, const char* name, const char* sig, bool is_static) {
   Class* c = Decode<Class*>(ts, jni_class);
   if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(c, true)) {
     return NULL;
@@ -359,13 +397,13 @@
   return EncodeField(field);
 }
 
-void PinPrimitiveArray(ScopedJniThreadState& ts, const Array* array) {
+static void PinPrimitiveArray(ScopedJniThreadState& ts, const Array* array) {
   JavaVMExt* vm = ts.Vm();
   MutexLock mu(vm->pins_lock);
   vm->pin_table.Add(array);
 }
 
-void UnpinPrimitiveArray(ScopedJniThreadState& ts, const Array* array) {
+static void UnpinPrimitiveArray(ScopedJniThreadState& ts, const Array* array) {
   JavaVMExt* vm = ts.Vm();
   MutexLock mu(vm->pins_lock);
   vm->pin_table.Remove(array);
@@ -396,13 +434,14 @@
   }
 }
 
-void ThrowAIOOBE(ScopedJniThreadState& ts, Array* array, jsize start, jsize length, const char* identifier) {
+static void ThrowAIOOBE(ScopedJniThreadState& ts, Array* array, jsize start, jsize length, const char* identifier) {
   std::string type(PrettyTypeOf(array));
   ts.Self()->ThrowNewExceptionF("Ljava/lang/ArrayIndexOutOfBoundsException;",
       "%s offset=%d length=%d %s.length=%d",
       type.c_str(), start, length, identifier, array->GetLength());
 }
-void ThrowSIOOBE(ScopedJniThreadState& ts, jsize start, jsize length, jsize array_length) {
+
+static void ThrowSIOOBE(ScopedJniThreadState& ts, jsize start, jsize length, jsize array_length) {
   ts.Self()->ThrowNewExceptionF("Ljava/lang/StringIndexOutOfBoundsException;",
       "offset=%d length=%d string.length()=%d", start, length, array_length);
 }
@@ -429,18 +468,18 @@
   }
 }
 
-jclass InitDirectByteBufferClass(JNIEnv* env) {
+static jclass InitDirectByteBufferClass(JNIEnv* env) {
   ScopedLocalRef<jclass> buffer_class(env, env->FindClass("java/nio/ReadWriteDirectByteBuffer"));
   CHECK(buffer_class.get() != NULL);
   return reinterpret_cast<jclass>(env->NewGlobalRef(buffer_class.get()));
 }
 
-jclass GetDirectByteBufferClass(JNIEnv* env) {
+static jclass GetDirectByteBufferClass(JNIEnv* env) {
   static jclass buffer_class = InitDirectByteBufferClass(env);
   return buffer_class;
 }
 
-jint JII_AttachCurrentThread(JavaVM* vm, JNIEnv** p_env, void* thr_args, bool as_daemon) {
+static jint JII_AttachCurrentThread(JavaVM* vm, JNIEnv** p_env, void* thr_args, bool as_daemon) {
   if (vm == NULL || p_env == NULL) {
     return JNI_ERR;
   }
diff --git a/src/jni_internal.h b/src/jni_internal.h
index 25e9e62..6950dae 100644
--- a/src/jni_internal.h
+++ b/src/jni_internal.h
@@ -60,6 +60,7 @@
   return reinterpret_cast<jmethodID>(method);
 }
 
+size_t NumArgArrayBytes(const char* shorty);
 JValue InvokeWithJValues(JNIEnv* env, jobject obj, jmethodID mid, jvalue* args);
 
 struct JavaVMExt : public JavaVM {
diff --git a/src/jni_internal_arm.cc b/src/jni_internal_arm.cc
index f1ed092..dadf7b4 100644
--- a/src/jni_internal_arm.cc
+++ b/src/jni_internal_arm.cc
@@ -29,14 +29,15 @@
 // register and transfer arguments from the array into register and on
 // the stack, if needed.  On return, the thread register must be
 // shuffled and the return value must be store into the result JValue.
-CompiledInvokeStub* ArmCreateInvokeStub(const Method* method) {
+CompiledInvokeStub* ArmCreateInvokeStub(bool is_static, const char* shorty) {
   UniquePtr<ArmAssembler> assembler(
       down_cast<ArmAssembler*>(Assembler::Create(kArm)));
 #define __ assembler->
+  size_t num_arg_array_bytes = NumArgArrayBytes(shorty);
   // Size of frame - spill of R4,R9/LR + Method* + possible receiver + arg array
   size_t unpadded_frame_size = (4 * kPointerSize) +
-                               (method->IsStatic() ? 0 : kPointerSize) +
-                               method->NumArgArrayBytes();
+                               (is_static ? 0 : kPointerSize) +
+                               num_arg_array_bytes;
   size_t frame_size = RoundUp(unpadded_frame_size, kStackAlignment);
 
   // Spill R4,R9 and LR
@@ -53,14 +54,14 @@
   __ AddConstant(SP, -frame_size + (3 * kPointerSize));
 
   // Can either get 3 or 2 arguments into registers
-  size_t reg_bytes = (method->IsStatic() ? 3 : 2) * kPointerSize;
+  size_t reg_bytes = (is_static ? 3 : 2) * kPointerSize;
   // Bytes passed by stack
   size_t stack_bytes;
-  if (method->NumArgArrayBytes() > reg_bytes) {
-    stack_bytes = method->NumArgArrayBytes() - reg_bytes;
+  if (num_arg_array_bytes > reg_bytes) {
+    stack_bytes = num_arg_array_bytes - reg_bytes;
   } else {
     stack_bytes = 0;
-    reg_bytes = method->NumArgArrayBytes();
+    reg_bytes = num_arg_array_bytes;
   }
 
   // Method* at bottom of frame is null thereby terminating managed stack crawls
@@ -75,12 +76,12 @@
 
     // we're displaced off of the arguments by the spill space for the incoming
     // arguments, the Method* and possibly the receiver
-    int sp_offset = reg_bytes + (method->IsStatic() ? 1 : 2) * kPointerSize + off;
+    int sp_offset = reg_bytes + (is_static ? 1 : 2) * kPointerSize + off;
     __ StoreToOffset(kStoreWord, IP, SP, sp_offset);
   }
 
   // Move all the register arguments into place.
-  if (method->IsStatic()) {
+  if (is_static) {
     if (reg_bytes > 0) {
       __ LoadFromOffset(kLoadWord, R1, R3, 0);
       if (reg_bytes > 4) {
@@ -100,16 +101,17 @@
   }
 
   // Load the code pointer we are about to call.
-  __ LoadFromOffset(kLoadWord, IP, R0, method->GetCodeOffset().Int32Value());
+  __ LoadFromOffset(kLoadWord, IP, R0, Method::GetCodeOffset().Int32Value());
 
   // Do the call.
   __ blx(IP);
 
   // If the method returns a value, store it to the result pointer.
-  if (!method->IsReturnVoid()) {
+  if (shorty[0] != 'V') {
     // Load the result JValue pointer of the stub caller's out args.
     __ LoadFromOffset(kLoadWord, IP, SP, frame_size);
-    __ StoreToOffset(method->IsReturnALongOrDouble() ? kStoreWordPair : kStoreWord, R0, IP, 0);
+    StoreOperandType type = (shorty[0] == 'J' || shorty[0] == 'D') ? kStoreWordPair : kStoreWord;
+    __ StoreToOffset(type, R0, IP, 0);
   }
 
   // Remove the frame less the spilled R4, R9 and LR
diff --git a/src/jni_internal_x86.cc b/src/jni_internal_x86.cc
index 891971d..7d931ba 100644
--- a/src/jni_internal_x86.cc
+++ b/src/jni_internal_x86.cc
@@ -25,14 +25,15 @@
 // "running" state the remaining responsibilities of this routine are
 // to save the native registers and set up the managed registers. On
 // return, the return value must be store into the result JValue.
-CompiledInvokeStub* X86CreateInvokeStub(const Method* method) {
+CompiledInvokeStub* X86CreateInvokeStub(bool is_static, const char* shorty) {
   UniquePtr<X86Assembler> assembler(
       down_cast<X86Assembler*>(Assembler::Create(kX86)));
 #define __ assembler->
+  size_t num_arg_array_bytes = NumArgArrayBytes(shorty);
   // Size of frame - return address + Method* + possible receiver + arg array
   size_t frame_size = (2 * kPointerSize) +
-                      (method->IsStatic() ? 0 : kPointerSize) +
-                      method->NumArgArrayBytes();
+                      (is_static ? 0 : kPointerSize) +
+                      num_arg_array_bytes;
   size_t pad_size = RoundUp(frame_size, kStackAlignment) - frame_size;
 
   __ movl(EAX, Address(ESP, 4));   // EAX = method
@@ -45,20 +46,20 @@
   }
 
   // Push/copy arguments
-  for (size_t off = method->NumArgArrayBytes(); off > 0; off -= kPointerSize) {
+  for (size_t off = num_arg_array_bytes; off > 0; off -= kPointerSize) {
     __ pushl(Address(EDX, off - kPointerSize));
   }
-  if (!method->IsStatic()) {
+  if (!is_static) {
     __ pushl(ECX);
   }
   // Push 0 as NULL Method* thereby terminating managed stack crawls
   __ pushl(Immediate(0));
 
-  __ call(Address(EAX, method->GetCodeOffset()));  // Call code off of method
+  __ call(Address(EAX, Method::GetCodeOffset()));  // Call code off of method
 
   // pop arguments up to the return address
   __ addl(ESP, Immediate(frame_size + pad_size - kPointerSize));
-  char ch = method->GetShorty()->CharAt(0);
+  char ch = shorty[0];
   if (ch != 'V') {
     // Load the result JValue pointer.
     __ movl(ECX, Address(ESP, 20));
diff --git a/src/monitor.cc b/src/monitor.cc
index b9a9459..3f041e4 100644
--- a/src/monitor.cc
+++ b/src/monitor.cc
@@ -831,7 +831,7 @@
   const DexFile& dex_file = class_linker->FindDexFile(dex_cache);
   const DexFile::ClassDef* class_def = dex_file.FindClassDef(c->GetDescriptor()->ToModifiedUtf8());
 
-  source_file = dex_file.dexGetSourceFile(*class_def);
+  source_file = dex_file.GetSourceFile(*class_def);
   line_number = dex_file.GetLineNumFromPC(method, method->ToDexPC(pc));
 }
 
diff --git a/src/oat.cc b/src/oat.cc
index 1a615fe..0089410 100644
--- a/src/oat.cc
+++ b/src/oat.cc
@@ -68,7 +68,6 @@
 OatMethodOffsets::OatMethodOffsets()
   : code_offset_(0),
     frame_size_in_bytes_(0),
-    return_pc_offset_in_bytes_(0),
     core_spill_mask_(0),
     fp_spill_mask_(0),
     mapping_table_offset_(0),
@@ -77,7 +76,6 @@
 
 OatMethodOffsets::OatMethodOffsets(uint32_t code_offset,
                                    uint32_t frame_size_in_bytes,
-                                   uint32_t return_pc_offset_in_bytes,
                                    uint32_t core_spill_mask,
                                    uint32_t fp_spill_mask,
                                    uint32_t mapping_table_offset,
@@ -85,7 +83,6 @@
                                    uint32_t invoke_stub_offset)
   : code_offset_(code_offset),
     frame_size_in_bytes_(frame_size_in_bytes),
-    return_pc_offset_in_bytes_(return_pc_offset_in_bytes),
     core_spill_mask_(core_spill_mask),
     fp_spill_mask_(fp_spill_mask),
     mapping_table_offset_(mapping_table_offset),
diff --git a/src/oat.h b/src/oat.h
index ff50599..0ffc80f 100644
--- a/src/oat.h
+++ b/src/oat.h
@@ -41,7 +41,6 @@
   OatMethodOffsets();
   OatMethodOffsets(uint32_t code_offset,
                    uint32_t frame_size_in_bytes,
-                   uint32_t return_pc_offset_in_bytes,
                    uint32_t core_spill_mask,
                    uint32_t fp_spill_mask,
                    uint32_t mapping_table_offset,
@@ -51,7 +50,6 @@
 
   uint32_t code_offset_;
   uint32_t frame_size_in_bytes_;
-  uint32_t return_pc_offset_in_bytes_;
   uint32_t core_spill_mask_;
   uint32_t fp_spill_mask_;
   uint32_t mapping_table_offset_;
diff --git a/src/oat_file.cc b/src/oat_file.cc
index 8af22b0..383bc2a 100644
--- a/src/oat_file.cc
+++ b/src/oat_file.cc
@@ -175,7 +175,6 @@
   return OatMethod(
       GetOatPointer<const void*>(oat_method_offsets.code_offset_),
       oat_method_offsets.frame_size_in_bytes_,
-      oat_method_offsets.return_pc_offset_in_bytes_,
       oat_method_offsets.core_spill_mask_,
       oat_method_offsets.fp_spill_mask_,
       GetOatPointer<const uint32_t*>(oat_method_offsets.mapping_table_offset_),
@@ -185,7 +184,6 @@
 
 OatFile::OatMethod::OatMethod(const void* code,
                               const size_t frame_size_in_bytes,
-                              const size_t return_pc_offset_in_bytes,
                               const uint32_t core_spill_mask,
                               const uint32_t fp_spill_mask,
                               const uint32_t* mapping_table,
@@ -193,7 +191,6 @@
                               const Method::InvokeStub* invoke_stub)
   : code_(code),
     frame_size_in_bytes_(frame_size_in_bytes),
-    return_pc_offset_in_bytes_(return_pc_offset_in_bytes),
     core_spill_mask_(core_spill_mask),
     fp_spill_mask_(fp_spill_mask),
     mapping_table_(mapping_table),
diff --git a/src/oat_file.h b/src/oat_file.h
index 1ee8c91..2c39e9d 100644
--- a/src/oat_file.h
+++ b/src/oat_file.h
@@ -40,7 +40,6 @@
     // Create an OatMethod backed by an OatFile
     OatMethod(const void* code,
               const size_t frame_size_in_bytes,
-              const size_t return_pc_offset_in_bytes,
               const uint32_t core_spill_mask,
               const uint32_t fp_spill_mask,
               const uint32_t* mapping_table,
@@ -54,7 +53,6 @@
 
     const void* code_;
     size_t frame_size_in_bytes_;
-    size_t return_pc_offset_in_bytes_;
     uint32_t core_spill_mask_;
     uint32_t fp_spill_mask_;
     const uint32_t* mapping_table_;
diff --git a/src/oat_test.cc b/src/oat_test.cc
index e90d2ed..e3186de 100644
--- a/src/oat_test.cc
+++ b/src/oat_test.cc
@@ -37,8 +37,11 @@
   for (size_t i = 0; i < dex_file.NumClassDefs(); i++) {
     const DexFile::ClassDef& class_def = dex_file.GetClassDef(i);
     const byte* class_data = dex_file.GetClassData(class_def);
-    DexFile::ClassDataHeader header = dex_file.ReadClassDataHeader(&class_data);
-    size_t num_virtual_methods = header.virtual_methods_size_;
+    size_t num_virtual_methods =0;
+    if (class_data != NULL) {
+      ClassDataItemIterator it(dex_file, class_data);
+      num_virtual_methods = it.NumVirtualMethods();
+    }
     const char* descriptor = dex_file.GetClassDescriptor(class_def);
 
     UniquePtr<const OatFile::OatClass> oat_class(oat_dex_file->GetOatClass(i));
@@ -49,12 +52,13 @@
     for (size_t i = 0; i < klass->NumDirectMethods(); i++, method_index++) {
       Method* method = klass->GetDirectMethod(i);
       const OatFile::OatMethod oat_method = oat_class->GetOatMethod(method_index);
-      const CompiledMethod* compiled_method = compiler_->GetCompiledMethod(method);
+      const CompiledMethod* compiled_method =
+          compiler_->GetCompiledMethod(Compiler::MethodReference(&dex_file,
+                                                                 method->GetDexMethodIndex()));
 
       if (compiled_method == NULL) {
         EXPECT_TRUE(oat_method.code_ == NULL) << PrettyMethod(method) << " " << oat_method.code_;
         EXPECT_EQ(oat_method.frame_size_in_bytes_, static_cast<uint32_t>(kStackAlignment));
-        EXPECT_EQ(oat_method.return_pc_offset_in_bytes_, 0U);
         EXPECT_EQ(oat_method.core_spill_mask_, 0U);
         EXPECT_EQ(oat_method.fp_spill_mask_, 0U);
       } else {
@@ -68,7 +72,6 @@
             << PrettyMethod(method) << " " << code_size;
         CHECK_EQ(0, memcmp(oat_code, &code[0], code_size));
         EXPECT_EQ(oat_method.frame_size_in_bytes_, compiled_method->GetFrameSizeInBytes());
-        EXPECT_EQ(oat_method.return_pc_offset_in_bytes_, compiled_method->GetReturnPcOffsetInBytes());
         EXPECT_EQ(oat_method.core_spill_mask_, compiled_method->GetCoreSpillMask());
         EXPECT_EQ(oat_method.fp_spill_mask_, compiled_method->GetFpSpillMask());
       }
@@ -76,12 +79,13 @@
     for (size_t i = 0; i < num_virtual_methods; i++, method_index++) {
       Method* method = klass->GetVirtualMethod(i);
       const OatFile::OatMethod oat_method = oat_class->GetOatMethod(method_index);
-      const CompiledMethod* compiled_method = compiler_->GetCompiledMethod(method);
+      const CompiledMethod* compiled_method =
+          compiler_->GetCompiledMethod(Compiler::MethodReference(&dex_file,
+                                                                 method->GetDexMethodIndex()));
 
       if (compiled_method == NULL) {
         EXPECT_TRUE(oat_method.code_ == NULL) << PrettyMethod(method) << " " << oat_method.code_;
         EXPECT_EQ(oat_method.frame_size_in_bytes_, static_cast<uint32_t>(kStackAlignment));
-        EXPECT_EQ(oat_method.return_pc_offset_in_bytes_, 0U);
         EXPECT_EQ(oat_method.core_spill_mask_, 0U);
         EXPECT_EQ(oat_method.fp_spill_mask_, 0U);
       } else {
@@ -96,7 +100,6 @@
             << PrettyMethod(method) << " " << code_size;
         CHECK_EQ(0, memcmp(oat_code, &code[0], code_size));
         EXPECT_EQ(oat_method.frame_size_in_bytes_, compiled_method->GetFrameSizeInBytes());
-        EXPECT_EQ(oat_method.return_pc_offset_in_bytes_, compiled_method->GetReturnPcOffsetInBytes());
         EXPECT_EQ(oat_method.core_spill_mask_, compiled_method->GetCoreSpillMask());
         EXPECT_EQ(oat_method.fp_spill_mask_, compiled_method->GetFpSpillMask());
       }
diff --git a/src/oat_writer.cc b/src/oat_writer.cc
index 664dcfe..f3e78e6 100644
--- a/src/oat_writer.cc
+++ b/src/oat_writer.cc
@@ -24,6 +24,8 @@
   compiler_ = &compiler;
   class_loader_ = class_loader;
   dex_files_ = &dex_files;
+  oat_header_ = NULL;
+  executable_offset_padding_length_ = 0;
 
   size_t offset = InitOatHeader();
   offset = InitOatDexFiles(offset);
@@ -36,6 +38,13 @@
   CHECK_EQ(dex_files_->size(), oat_classes_.size());
 }
 
+OatWriter::~OatWriter() {
+  delete oat_header_;
+  STLDeleteElements(&oat_dex_files_);
+  STLDeleteElements(&oat_classes_);
+  STLDeleteElements(&oat_methods_);
+}
+
 size_t OatWriter::InitOatHeader() {
   // create the OatHeader
   oat_header_ = new OatHeader(dex_files_);
@@ -83,10 +92,13 @@
       oat_classes_[i]->methods_offsets_[class_def_index] = offset;
       const DexFile::ClassDef& class_def = dex_file->GetClassDef(class_def_index);
       const byte* class_data = dex_file->GetClassData(class_def);
-      DexFile::ClassDataHeader header = dex_file->ReadClassDataHeader(&class_data);
-      size_t num_direct_methods = header.direct_methods_size_;
-      size_t num_virtual_methods = header.virtual_methods_size_;
-      uint32_t num_methods = num_direct_methods + num_virtual_methods;
+      uint32_t num_methods = 0;
+      if (class_data != NULL) {  // ie not an empty class, such as a marker interface
+        ClassDataItemIterator it(*dex_file, class_data);
+        size_t num_direct_methods = it.NumDirectMethods();
+        size_t num_virtual_methods = it.NumVirtualMethods();
+        num_methods = num_direct_methods + num_virtual_methods;
+      }
       OatMethods* oat_methods = new OatMethods(num_methods);
       oat_methods_.push_back(oat_methods);
       offset += oat_methods->SizeOf();
@@ -135,46 +147,46 @@
                                       const DexFile& dex_file,
                                       const DexFile::ClassDef& class_def) {
   const byte* class_data = dex_file.GetClassData(class_def);
-  DexFile::ClassDataHeader header = dex_file.ReadClassDataHeader(&class_data);
-  size_t num_virtual_methods = header.virtual_methods_size_;
-  const char* descriptor = dex_file.GetClassDescriptor(class_def);
-
-  // TODO: remove code ByteArrays from Class/Method (and therefore ClassLoader)
-  // TODO: don't write code for shared stubs
-  Class* klass = Runtime::Current()->GetClassLinker()->FindClass(descriptor, class_loader_);
-  if (klass == NULL) {
-    LOG(WARNING) << "Didn't find class '" << descriptor << "' in dex file " << dex_file.GetLocation();
-    Thread* thread = Thread::Current();
-    DCHECK(thread->IsExceptionPending());
-    thread->ClearException();
+  if (class_data == NULL) {
+    // empty class, such as a marker interface
     return offset;
   }
-  CHECK_EQ(klass->GetClassLoader(), class_loader_);
+  ClassDataItemIterator it(dex_file, class_data);
   CHECK_EQ(oat_methods_[oat_class_index]->method_offsets_.size(),
-           klass->NumDirectMethods() + num_virtual_methods);
+           it.NumDirectMethods() + it.NumVirtualMethods());
+  // Skip fields
+  while (it.HasNextStaticField()) {
+    it.Next();
+  }
+  while (it.HasNextInstanceField()) {
+    it.Next();
+  }
+  // Process methods
   size_t class_def_method_index = 0;
-  for (size_t i = 0; i < klass->NumDirectMethods(); i++, class_def_method_index++) {
-    Method* method = klass->GetDirectMethod(i);
-    CHECK(method != NULL) << descriptor << " direct " << i;
-    offset = InitOatCodeMethod(offset, oat_class_index, class_def_method_index, method);
+  while (it.HasNextDirectMethod()) {
+    bool is_static = (it.GetMemberAccessFlags() & kAccStatic) != 0;
+    offset = InitOatCodeMethod(offset, oat_class_index, class_def_method_index, is_static, true,
+                               it.GetMemberIndex(), &dex_file);
+    class_def_method_index++;
+    it.Next();
   }
-  // note that num_virtual_methods != klass->NumVirtualMethods() because of miranda methods
-  for (size_t i = 0; i < num_virtual_methods; i++, class_def_method_index++) {
-    Method* method = klass->GetVirtualMethod(i);
-    CHECK(method != NULL) << descriptor << " virtual " << i;
-    offset = InitOatCodeMethod(offset, oat_class_index, class_def_method_index, method);
+  while (it.HasNextVirtualMethod()) {
+    CHECK_EQ(it.GetMemberAccessFlags() & kAccStatic, 0U);
+    offset = InitOatCodeMethod(offset, oat_class_index, class_def_method_index, false, false,
+                               it.GetMemberIndex(), &dex_file);
+    class_def_method_index++;
+    it.Next();
   }
+  DCHECK(!it.HasNext());
   return offset;
 }
 
-size_t OatWriter::InitOatCodeMethod(size_t offset,
-                                    size_t oat_class_index,
-                                    size_t class_def_method_index,
-                                    Method* method) {
+size_t OatWriter::InitOatCodeMethod(size_t offset, size_t oat_class_index,
+                                    size_t class_def_method_index, bool is_static, bool is_direct,
+                                    uint32_t method_idx, const DexFile* dex_file) {
   // derived from CompiledMethod if available
   uint32_t code_offset = 0;
   uint32_t frame_size_in_bytes = kStackAlignment;
-  uint32_t return_pc_offset_in_bytes = 0;
   uint32_t core_spill_mask = 0;
   uint32_t fp_spill_mask = 0;
   uint32_t mapping_table_offset = 0;
@@ -182,7 +194,8 @@
   // derived from CompiledInvokeStub if available
   uint32_t invoke_stub_offset = 0;
 
-  const CompiledMethod* compiled_method = compiler_->GetCompiledMethod(method);
+  CompiledMethod* compiled_method =
+      compiler_->GetCompiledMethod(art::Compiler::MethodReference(dex_file, method_idx));
   if (compiled_method != NULL) {
     offset = compiled_method->AlignCode(offset);
     DCHECK_ALIGNED(offset, kArmAlignment);
@@ -202,7 +215,6 @@
     }
 
     frame_size_in_bytes = compiled_method->GetFrameSizeInBytes();
-    return_pc_offset_in_bytes = compiled_method->GetReturnPcOffsetInBytes();
     core_spill_mask = compiled_method->GetCoreSpillMask();
     fp_spill_mask = compiled_method->GetFpSpillMask();
   }
@@ -210,9 +222,6 @@
   offset += sizeof(frame_size_in_bytes);
   oat_header_->UpdateChecksum(&frame_size_in_bytes, sizeof(frame_size_in_bytes));
 
-  offset += sizeof(return_pc_offset_in_bytes);
-  oat_header_->UpdateChecksum(&return_pc_offset_in_bytes, sizeof(return_pc_offset_in_bytes));
-
   offset += sizeof(core_spill_mask);
   oat_header_->UpdateChecksum(&core_spill_mask, sizeof(core_spill_mask));
 
@@ -249,7 +258,8 @@
     }
   }
 
-  const CompiledInvokeStub* compiled_invoke_stub = compiler_->GetCompiledInvokeStub(method);
+  const char* shorty = dex_file->GetMethodShorty(dex_file->GetMethodId(method_idx));
+  const CompiledInvokeStub* compiled_invoke_stub = compiler_->FindInvokeStub(is_static, shorty);
   if (compiled_invoke_stub != NULL) {
     offset = CompiledMethod::AlignCode(offset, compiler_->GetInstructionSet());
     DCHECK_ALIGNED(offset, kArmAlignment);
@@ -271,22 +281,26 @@
   oat_methods_[oat_class_index]->method_offsets_[class_def_method_index]
       = OatMethodOffsets(code_offset,
                          frame_size_in_bytes,
-                         return_pc_offset_in_bytes,
                          core_spill_mask,
                          fp_spill_mask,
                          mapping_table_offset,
                          vmap_table_offset,
                          invoke_stub_offset);
 
-  // Note that we leave the offset and values back in the Method where ImageWriter will find them
-  method->SetOatCodeOffset(code_offset);
-  method->SetFrameSizeInBytes(frame_size_in_bytes);
-  method->SetCoreSpillMask(core_spill_mask);
-  method->SetFpSpillMask(fp_spill_mask);
-  method->SetOatMappingTableOffset(mapping_table_offset);
-  method->SetOatVmapTableOffset(vmap_table_offset);
-  method->SetOatInvokeStubOffset(invoke_stub_offset);
-
+  if (compiler_->IsImage()) {
+    ClassLinker* linker = Runtime::Current()->GetClassLinker();
+    DexCache* dex_cache = linker->FindDexCache(*dex_file);
+    Method* method = linker->ResolveMethod(*dex_file, method_idx, dex_cache, class_loader_,
+                                           is_direct);
+    CHECK(method != NULL);
+    method->SetFrameSizeInBytes(frame_size_in_bytes);
+    method->SetCoreSpillMask(core_spill_mask);
+    method->SetFpSpillMask(fp_spill_mask);
+    method->SetOatMappingTableOffset(mapping_table_offset);
+    method->SetOatCodeOffset(code_offset);
+    method->SetOatVmapTableOffset(vmap_table_offset);
+    method->SetOatInvokeStubOffset(invoke_stub_offset);
+  }
   return offset;
 }
 
@@ -354,10 +368,11 @@
 }
 
 size_t OatWriter::WriteCodeDexFiles(File* file, size_t code_offset) {
+  size_t oat_class_index = 0;
   for (size_t i = 0; i != oat_classes_.size(); ++i) {
     const DexFile* dex_file = (*dex_files_)[i];
     CHECK(dex_file != NULL);
-    code_offset = WriteCodeDexFile(file, code_offset, *dex_file);
+    code_offset = WriteCodeDexFile(file, code_offset, oat_class_index, *dex_file);
     if (code_offset == 0) {
       return 0;
     }
@@ -365,10 +380,12 @@
   return code_offset;
 }
 
-size_t OatWriter::WriteCodeDexFile(File* file, size_t code_offset, const DexFile& dex_file) {
-  for (size_t class_def_index = 0; class_def_index < dex_file.NumClassDefs(); class_def_index++) {
+size_t OatWriter::WriteCodeDexFile(File* file, size_t code_offset, size_t& oat_class_index,
+                                   const DexFile& dex_file) {
+  for (size_t class_def_index = 0; class_def_index < dex_file.NumClassDefs();
+      class_def_index++, oat_class_index++) {
     const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index);
-    code_offset = WriteCodeClassDef(file, code_offset, dex_file, class_def);
+    code_offset = WriteCodeClassDef(file, code_offset, oat_class_index, dex_file, class_def);
     if (code_offset == 0) {
       return 0;
     }
@@ -376,54 +393,68 @@
   return code_offset;
 }
 
-void OatWriter::ReportWriteFailure(const char* what, Method* m, File* f) {
-  PLOG(ERROR) << "Failed to write " << what << " for " << PrettyMethod(m) << " to " << f->name();
+void OatWriter::ReportWriteFailure(const char* what, uint32_t method_idx,
+                                   const DexFile& dex_file, File* f) const {
+  PLOG(ERROR) << "Failed to write " << what << " for " << PrettyMethod(method_idx, dex_file)
+      << " to " << f->name();
 }
 
 size_t OatWriter::WriteCodeClassDef(File* file,
-                                    size_t code_offset,
+                                    size_t code_offset, size_t oat_class_index,
                                     const DexFile& dex_file,
                                     const DexFile::ClassDef& class_def) {
   const byte* class_data = dex_file.GetClassData(class_def);
-  DexFile::ClassDataHeader header = dex_file.ReadClassDataHeader(&class_data);
-  size_t num_virtual_methods = header.virtual_methods_size_;
-  const char* descriptor = dex_file.GetClassDescriptor(class_def);
-  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
-  Class* klass = class_linker->FindClass(descriptor, class_loader_);
-  if (klass == NULL) {
-    LOG(WARNING) << "Didn't find class '" << descriptor << "' in dex file " << dex_file.GetLocation();
-    Thread* thread = Thread::Current();
-    DCHECK(thread->IsExceptionPending());
-    thread->ClearException();
+  if (class_data == NULL) {
+    // ie. an empty class such as a marker interface
     return code_offset;
   }
-
-  // Note that we clear the code array here, image_writer will use GetCodeOffset to find it
-  for (size_t i = 0; i < klass->NumDirectMethods(); i++) {
-    Method* method = klass->GetDirectMethod(i);
-    code_offset = WriteCodeMethod(file, code_offset, method);
+  ClassDataItemIterator it(dex_file, class_data);
+  // Skip fields
+  while (it.HasNextStaticField()) {
+    it.Next();
+  }
+  while (it.HasNextInstanceField()) {
+    it.Next();
+  }
+  // Process methods
+  size_t class_def_method_index = 0;
+  while (it.HasNextDirectMethod()) {
+    bool is_static = (it.GetMemberAccessFlags() & kAccStatic) != 0;
+    code_offset = WriteCodeMethod(file, code_offset, oat_class_index, class_def_method_index,
+                                  is_static, it.GetMemberIndex(), dex_file);
     if (code_offset == 0) {
       return 0;
     }
+    class_def_method_index++;
+    it.Next();
   }
-  // note that num_virtual_methods != klass->NumVirtualMethods() because of miranda methods
-  for (size_t i = 0; i < num_virtual_methods; i++) {
-    Method* method = klass->GetVirtualMethod(i);
-    code_offset = WriteCodeMethod(file, code_offset, method);
+  while (it.HasNextVirtualMethod()) {
+    code_offset = WriteCodeMethod(file, code_offset, oat_class_index, class_def_method_index,
+                                  false, it.GetMemberIndex(), dex_file);
     if (code_offset == 0) {
       return 0;
     }
-  }
-  for (size_t i = num_virtual_methods; i < klass->NumVirtualMethods(); i++) {
-    Method* method = klass->GetVirtualMethod(i);
-    CHECK(compiler_->GetCompiledMethod(method) == NULL) << PrettyMethod(method);
+    class_def_method_index++;
+    it.Next();
   }
   return code_offset;
 }
 
-size_t OatWriter::WriteCodeMethod(File* file, size_t code_offset, Method* method) {
-  const CompiledMethod* compiled_method = compiler_->GetCompiledMethod(method);
-  if (compiled_method != NULL) {
+size_t OatWriter::WriteCodeMethod(File* file, size_t code_offset, size_t oat_class_index,
+                                  size_t class_def_method_index, bool is_static,
+                                  uint32_t method_idx, const DexFile& dex_file) {
+  const CompiledMethod* compiled_method =
+      compiler_->GetCompiledMethod(art::Compiler::MethodReference(&dex_file, method_idx));
+
+  uint32_t frame_size_in_bytes = 0;
+  uint32_t core_spill_mask = 0;
+  uint32_t fp_spill_mask = 0;
+
+  OatMethodOffsets method_offsets =
+      oat_methods_[oat_class_index]->method_offsets_[class_def_method_index];
+
+
+  if (compiled_method != NULL) {  // ie. not an abstract method
     uint32_t aligned_code_offset = compiled_method->AlignCode(code_offset);
     uint32_t aligned_code_delta = aligned_code_offset - code_offset;
     if (aligned_code_delta != 0) {
@@ -443,42 +474,38 @@
     // Deduplicate code arrays
     size_t offset = code_offset + compiled_method->CodeDelta();
     std::map<const std::vector<uint8_t>*, uint32_t>::iterator code_iter = code_offsets_.find(&code);
-    if (code_iter != code_offsets_.end() && offset != method->GetOatCodeOffset()) {
-      DCHECK((code_size == 0 && method->GetOatCodeOffset() == 0)
-             || code_iter->second == method->GetOatCodeOffset()) << PrettyMethod(method);
+    if (code_iter != code_offsets_.end() && offset != method_offsets.code_offset_) {
+      DCHECK((code_size == 0 && method_offsets.code_offset_ == 0)
+             || code_iter->second == method_offsets.code_offset_)
+             << PrettyMethod(method_idx, dex_file);
     } else {
-      DCHECK((code_size == 0 && method->GetOatCodeOffset() == 0)
-             || offset == method->GetOatCodeOffset()) << PrettyMethod(method);
+      DCHECK((code_size == 0 && method_offsets.code_offset_ == 0)
+             || offset == method_offsets.code_offset_)
+             << PrettyMethod(method_idx, dex_file);
       if (!file->WriteFully(&code[0], code_size)) {
-        ReportWriteFailure("method code", method, file);
+        ReportWriteFailure("method code", method_idx, dex_file, file);
         return false;
       }
       code_offset += code_size;
     }
     DCHECK_CODE_OFFSET();
+    frame_size_in_bytes = compiled_method->GetFrameSizeInBytes();
+    core_spill_mask = compiled_method->GetCoreSpillMask();
+    fp_spill_mask = compiled_method->GetFpSpillMask();
   }
 
-  uint32_t frame_size_in_bytes = method->GetFrameSizeInBytes();
-  uint32_t return_pc_offset_in_bytes = method->GetReturnPcOffsetInBytes();
-  uint32_t core_spill_mask = method->GetCoreSpillMask();
-  uint32_t fp_spill_mask = method->GetFpSpillMask();
   if (!file->WriteFully(&frame_size_in_bytes, sizeof(frame_size_in_bytes))) {
-    ReportWriteFailure("method frame size", method, file);
+    ReportWriteFailure("method frame size", method_idx, dex_file, file);
     return false;
   }
   code_offset += sizeof(frame_size_in_bytes);
-  if (!file->WriteFully(&return_pc_offset_in_bytes, sizeof(return_pc_offset_in_bytes))) {
-    ReportWriteFailure("method return pc", method, file);
-    return false;
-  }
-  code_offset += sizeof(return_pc_offset_in_bytes);
   if (!file->WriteFully(&core_spill_mask, sizeof(core_spill_mask))) {
-    ReportWriteFailure("method core spill mask", method, file);
+    ReportWriteFailure("method core spill mask", method_idx, dex_file, file);
     return false;
   }
   code_offset += sizeof(core_spill_mask);
   if (!file->WriteFully(&fp_spill_mask, sizeof(fp_spill_mask))) {
-    ReportWriteFailure("method fp spill mask", method, file);
+    ReportWriteFailure("method fp spill mask", method_idx, dex_file, file);
     return false;
   }
   code_offset += sizeof(fp_spill_mask);
@@ -488,15 +515,19 @@
     size_t mapping_table_size = mapping_table.size() * sizeof(mapping_table[0]);
 
     // Deduplicate mapping tables
-    std::map<const std::vector<uint32_t>*, uint32_t>::iterator mapping_iter = mapping_table_offsets_.find(&mapping_table);
-    if (mapping_iter != mapping_table_offsets_.end() && code_offset != method->GetOatMappingTableOffset()) {
-      DCHECK((mapping_table_size == 0 && method->GetOatMappingTableOffset() == 0)
-          || mapping_iter->second == method->GetOatMappingTableOffset()) << PrettyMethod(method);
+    std::map<const std::vector<uint32_t>*, uint32_t>::iterator mapping_iter =
+        mapping_table_offsets_.find(&mapping_table);
+    if (mapping_iter != mapping_table_offsets_.end() &&
+        code_offset != method_offsets.mapping_table_offset_) {
+      DCHECK((mapping_table_size == 0 && method_offsets.mapping_table_offset_ == 0)
+          || mapping_iter->second == method_offsets.mapping_table_offset_)
+          << PrettyMethod(method_idx, dex_file);
     } else {
-      DCHECK((mapping_table_size == 0 && method->GetOatMappingTableOffset() == 0)
-          || code_offset == method->GetOatMappingTableOffset()) << PrettyMethod(method);
+      DCHECK((mapping_table_size == 0 && method_offsets.mapping_table_offset_ == 0)
+          || code_offset == method_offsets.mapping_table_offset_)
+          << PrettyMethod(method_idx, dex_file);
       if (!file->WriteFully(&mapping_table[0], mapping_table_size)) {
-        ReportWriteFailure("mapping table", method, file);
+        ReportWriteFailure("mapping table", method_idx, dex_file, file);
         return false;
       }
       code_offset += mapping_table_size;
@@ -507,23 +538,27 @@
     size_t vmap_table_size = vmap_table.size() * sizeof(vmap_table[0]);
 
     // Deduplicate vmap tables
-    std::map<const std::vector<uint16_t>*, uint32_t>::iterator vmap_iter = vmap_table_offsets_.find(&vmap_table);
-    if (vmap_iter != vmap_table_offsets_.end() && code_offset != method->GetOatVmapTableOffset()) {
-      DCHECK((vmap_table_size == 0 && method->GetOatVmapTableOffset() == 0)
-          || vmap_iter->second == method->GetOatVmapTableOffset()) << PrettyMethod(method);
+    std::map<const std::vector<uint16_t>*, uint32_t>::iterator vmap_iter =
+        vmap_table_offsets_.find(&vmap_table);
+    if (vmap_iter != vmap_table_offsets_.end() &&
+        code_offset != method_offsets.vmap_table_offset_) {
+      DCHECK((vmap_table_size == 0 && method_offsets.vmap_table_offset_ == 0)
+          || vmap_iter->second == method_offsets.vmap_table_offset_)
+          << PrettyMethod(method_idx, dex_file);
     } else {
-      DCHECK((vmap_table_size == 0 && method->GetOatVmapTableOffset() == 0)
-          || code_offset == method->GetOatVmapTableOffset()) << PrettyMethod(method);
+      DCHECK((vmap_table_size == 0 && method_offsets.vmap_table_offset_ == 0)
+          || code_offset == method_offsets.vmap_table_offset_)
+          << PrettyMethod(method_idx, dex_file);
       if (!file->WriteFully(&vmap_table[0], vmap_table_size)) {
-        ReportWriteFailure("vmap table", method, file);
+        ReportWriteFailure("vmap table", method_idx, dex_file, file);
         return false;
       }
       code_offset += vmap_table_size;
     }
     DCHECK_CODE_OFFSET();
   }
-
-  const CompiledInvokeStub* compiled_invoke_stub = compiler_->GetCompiledInvokeStub(method);
+  const char* shorty = dex_file.GetMethodShorty(dex_file.GetMethodId(method_idx));
+  const CompiledInvokeStub* compiled_invoke_stub = compiler_->FindInvokeStub(is_static, shorty);
   if (compiled_invoke_stub != NULL) {
     uint32_t aligned_code_offset = CompiledMethod::AlignCode(code_offset,
                                                              compiler_->GetInstructionSet());
@@ -543,37 +578,34 @@
     size_t invoke_stub_size = invoke_stub.size() * sizeof(invoke_stub[0]);
 
     // Deduplicate invoke stubs
-    std::map<const std::vector<uint8_t>*, uint32_t>::iterator stub_iter = code_offsets_.find(&invoke_stub);
-    if (stub_iter != code_offsets_.end() && code_offset != method->GetOatInvokeStubOffset()) {
-      DCHECK((invoke_stub_size == 0 && method->GetOatInvokeStubOffset() == 0)
-          || stub_iter->second == method->GetOatInvokeStubOffset()) << PrettyMethod(method);
+    std::map<const std::vector<uint8_t>*, uint32_t>::iterator stub_iter =
+        code_offsets_.find(&invoke_stub);
+    if (stub_iter != code_offsets_.end() &&
+        code_offset != method_offsets.invoke_stub_offset_) {
+      DCHECK((invoke_stub_size == 0 && method_offsets.invoke_stub_offset_ == 0)
+          || stub_iter->second == method_offsets.invoke_stub_offset_)
+          << PrettyMethod(method_idx, dex_file);
     } else {
-      DCHECK((invoke_stub_size == 0 && method->GetOatInvokeStubOffset() == 0)
-          || code_offset == method->GetOatInvokeStubOffset()) << PrettyMethod(method);
+      DCHECK((invoke_stub_size == 0 && method_offsets.invoke_stub_offset_ == 0)
+          || code_offset == method_offsets.invoke_stub_offset_)
+          << PrettyMethod(method_idx, dex_file);
       if (!file->WriteFully(&invoke_stub[0], invoke_stub_size)) {
-        ReportWriteFailure("invoke stub code", method, file);
+        ReportWriteFailure("invoke stub code", method_idx, dex_file, file);
         return false;
       }
       code_offset += invoke_stub_size;
     }
     DCHECK_CODE_OFFSET();
   }
-
   return code_offset;
 }
 
-OatWriter::~OatWriter() {
-  delete oat_header_;
-  STLDeleteElements(&oat_dex_files_);
-  STLDeleteElements(&oat_classes_);
-  STLDeleteElements(&oat_methods_);
-}
-
 OatWriter::OatDexFile::OatDexFile(const DexFile& dex_file) {
   const std::string& location = dex_file.GetLocation();
   dex_file_location_size_ = location.size();
   dex_file_location_data_ = reinterpret_cast<const uint8_t*>(location.data());
   dex_file_checksum_ = dex_file.GetHeader().checksum_;
+  classes_offset_ = 0;
 }
 
 size_t OatWriter::OatDexFile::SizeOf() const {
diff --git a/src/oat_writer.h b/src/oat_writer.h
index 0642fa4..97cdb50 100644
--- a/src/oat_writer.h
+++ b/src/oat_writer.h
@@ -71,28 +71,23 @@
                              size_t oat_class_index,
                              const DexFile& dex_file,
                              const DexFile::ClassDef& class_def);
-  size_t InitOatCodeMethod(size_t offset,
-                           size_t oat_class_index,
-                           size_t class_def_method_index,
-                           Method* method);
+  size_t InitOatCodeMethod(size_t offset, size_t oat_class_index, size_t class_def_method_index,
+                           bool is_static, bool is_direct, uint32_t method_idx, const DexFile*);
 
   bool Write(File* file);
   bool WriteTables(File* file);
   size_t WriteCode(File* file);
-  size_t WriteCodeDexFiles(File* file,
-                           size_t offset);
-  size_t WriteCodeDexFile(File* file,
-                          size_t offset,
+  size_t WriteCodeDexFiles(File* file, size_t offset);
+  size_t WriteCodeDexFile(File* file, size_t offset, size_t& oat_class_index,
                           const DexFile& dex_file);
-  size_t WriteCodeClassDef(File* file,
-                           size_t offset,
-                           const DexFile& dex_file,
-                           const DexFile::ClassDef& class_def);
-  size_t WriteCodeMethod(File* file,
-                         size_t offset,
-                         Method* method);
+  size_t WriteCodeClassDef(File* file, size_t offset, size_t oat_class_index,
+                           const DexFile& dex_file, const DexFile::ClassDef& class_def);
+  size_t WriteCodeMethod(File* file, size_t offset, size_t oat_class_index,
+                         size_t class_def_method_index, bool is_static, uint32_t method_idx,
+                         const DexFile& dex_file);
 
-  void ReportWriteFailure(const char* what, Method* m, File* f);
+  void ReportWriteFailure(const char* what, uint32_t method_idx, const DexFile& dex_file,
+                          File* f) const;
 
   class OatDexFile {
    public:
diff --git a/src/oatdump.cc b/src/oatdump.cc
index 61f352e..8b0ada4 100644
--- a/src/oatdump.cc
+++ b/src/oatdump.cc
@@ -136,47 +136,33 @@
                            const DexFile& dex_file,
                            const DexFile::ClassDef& class_def) {
     const byte* class_data = dex_file.GetClassData(class_def);
-    DexFile::ClassDataHeader header = dex_file.ReadClassDataHeader(&class_data);
-    size_t num_static_fields = header.static_fields_size_;
-    size_t num_instance_fields = header.instance_fields_size_;
-    size_t num_direct_methods = header.direct_methods_size_;
-    size_t num_virtual_methods = header.virtual_methods_size_;
-    uint32_t method_index = 0;
+    if (class_data == NULL) {  // empty class such as a marker interface?
+      return;
+    }
+    ClassDataItemIterator it(dex_file, class_data);
 
     // just skipping through the fields to advance class_data
-    if (num_static_fields != 0) {
-      uint32_t last_idx = 0;
-      for (size_t i = 0; i < num_static_fields; ++i) {
-        DexFile::Field dex_field;
-        dex_file.dexReadClassDataField(&class_data, &dex_field, &last_idx);
-      }
+    while (it.HasNextStaticField()) {
+      it.Next();
     }
-    if (num_instance_fields != 0) {
-      uint32_t last_idx = 0;
-      for (size_t i = 0; i < num_instance_fields; ++i) {
-        DexFile::Field dex_field;
-        dex_file.dexReadClassDataField(&class_data, &dex_field, &last_idx);
-      }
+    while (it.HasNextInstanceField()) {
+      it.Next();
     }
 
-    if (num_direct_methods != 0) {
-      uint32_t last_idx = 0;
-      for (size_t i = 0; i < num_direct_methods; ++i, method_index++) {
-        DexFile::Method dex_method;
-        dex_file.dexReadClassDataMethod(&class_data, &dex_method, &last_idx);
-        const OatFile::OatMethod oat_method = oat_class.GetOatMethod(method_index);
-        DumpOatMethod(os, method_index, oat_file, oat_method, dex_file, dex_method);
-      }
+    uint32_t method_index = 0;
+    while (it.HasNextDirectMethod()) {
+      const OatFile::OatMethod oat_method = oat_class.GetOatMethod(method_index);
+      DumpOatMethod(os, method_index, oat_file, oat_method, dex_file, it.GetMemberIndex());
+      method_index++;
+      it.Next();
     }
-    if (num_virtual_methods != 0) {
-      uint32_t last_idx = 0;
-      for (size_t i = 0; i < num_virtual_methods; ++i, method_index++) {
-        DexFile::Method dex_method;
-        dex_file.dexReadClassDataMethod(&class_data, &dex_method, &last_idx);
-        const OatFile::OatMethod oat_method = oat_class.GetOatMethod(method_index);
-        DumpOatMethod(os, method_index, oat_file, oat_method, dex_file, dex_method);
-      }
+    while (it.HasNextVirtualMethod()) {
+      const OatFile::OatMethod oat_method = oat_class.GetOatMethod(method_index);
+      DumpOatMethod(os, method_index, oat_file, oat_method, dex_file, it.GetMemberIndex());
+      method_index++;
+      it.Next();
     }
+    DCHECK(!it.HasNext());
     os << std::flush;
   }
   static void DumpOatMethod(std::ostream& os,
@@ -184,19 +170,17 @@
                             const OatFile& oat_file,
                             const OatFile::OatMethod& oat_method,
                             const DexFile& dex_file,
-                            const DexFile::Method& dex_method) {
-    const DexFile::MethodId& method_id = dex_file.GetMethodId(dex_method.method_idx_);
+                            uint32_t method_idx) {
+    const DexFile::MethodId& method_id = dex_file.GetMethodId(method_idx);
     const char* name = dex_file.GetMethodName(method_id);
     std::string signature = dex_file.GetMethodSignature(method_id);
     os << StringPrintf("\t%d: %s %s (method_idx=%d)\n",
-                       method_index, name, signature.c_str(), dex_method.method_idx_);
+                       method_index, name, signature.c_str(), method_idx);
     os << StringPrintf("\t\tcode: %p (offset=%08x)\n",
                        oat_method.code_,
                        reinterpret_cast<const byte*>(oat_method.code_) - oat_file.GetBase());
     os << StringPrintf("\t\tframe_size_in_bytes: %d\n",
                        oat_method.frame_size_in_bytes_);
-    os << StringPrintf("\t\treturn_pc_offset_in_bytes: %d\n",
-                       oat_method.return_pc_offset_in_bytes_);
     os << StringPrintf("\t\tcore_spill_mask: %08x\n",
                        oat_method.core_spill_mask_);
     os << StringPrintf("\t\tfp_spill_mask: %08x\n",
diff --git a/src/object.cc b/src/object.cc
index 9cc0e3a..3954b3d 100644
--- a/src/object.cc
+++ b/src/object.cc
@@ -20,6 +20,7 @@
 #include "monitor.h"
 #include "runtime.h"
 #include "stack.h"
+#include "utils.h"
 
 namespace art {
 
@@ -122,7 +123,7 @@
 const char* Field::GetTypeDescriptor() const {
   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
   const DexFile& dex_file = class_linker->FindDexFile(GetDeclaringClass()->GetDexCache());
-  const char* descriptor = dex_file.dexStringByTypeIdx(GetTypeIdx());
+  const char* descriptor = dex_file.StringByTypeIdx(GetTypeIdx());
   DCHECK(descriptor != NULL);
   return descriptor;
 }
@@ -136,6 +137,15 @@
   return type;
 }
 
+void Field::SetOffset(MemberOffset num_bytes) {
+  DCHECK(GetDeclaringClass()->IsLoaded() || GetDeclaringClass()->IsErroneous());
+  Primitive::Type type = GetPrimitiveType();
+  if (type == Primitive::kPrimDouble || type == Primitive::kPrimLong) {
+    DCHECK_ALIGNED(num_bytes.Uint32Value(), 8);
+  }
+  SetField32(OFFSET_OF_OBJECT_MEMBER(Field, offset_), num_bytes.Uint32Value(), false);
+}
+
 void Field::InitJavaFields() {
   Thread* self = Thread::Current();
   ScopedThreadStateChange tsc(self, Thread::kRunnable);
@@ -405,12 +415,43 @@
              new_return_type_idx, false);
 }
 
+uint32_t Method::GetDexMethodIndex() const {
+  // TODO: add the method index to Method - which will also mean a number of Method fields can
+  // become dex file lookups (which will then mean we may want faster access to the dex file)
+  // Find the dex file
+  const DexCache* dex_cache = GetDeclaringClass()->GetDexCache();
+  const DexFile& dex_file = Runtime::Current()->GetClassLinker()->FindDexFile(dex_cache);
+  // Find the class_def in the dex file
+  uint32_t class_def_idx;
+  bool found_class_def =
+      dex_file.FindClassDefIndex(GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8(),
+                                 class_def_idx);
+  CHECK(found_class_def);
+  const DexFile::TypeId& type_id =
+      dex_file.GetTypeId(dex_file.GetClassDef(class_def_idx).class_idx_);
+  const DexFile::StringId* name_str_id = dex_file.FindStringId(GetName()->ToModifiedUtf8());
+  CHECK(name_str_id != NULL);  // Failed to find method's name?
+  uint16_t return_type_idx;
+  std::vector<uint16_t> param_type_idxs;
+  std::string signature = GetSignature()->ToModifiedUtf8();
+  bool found_type_list = dex_file.CreateTypeList(&return_type_idx, &param_type_idxs, signature);
+  CHECK(found_type_list);   // Failed to parse signature
+  const DexFile::ProtoId* sig_proto_id = dex_file.FindProtoId(return_type_idx, param_type_idxs);
+  CHECK(sig_proto_id != NULL);  // Failed to find method's prototype
+  const DexFile::MethodId* method_id =
+      dex_file.FindMethodId(type_id, *name_str_id, *sig_proto_id);
+  CHECK(method_id != NULL);  // Failed to find method?
+  uint32_t method_idx = dex_file.GetIndexForMethodId(*method_id);
+  DCHECK_EQ(PrettyMethod(method_idx, dex_file), PrettyMethod(this));
+  return method_idx;
+}
+
 const char* Method::GetReturnTypeDescriptor() const {
   Class* declaring_class = GetDeclaringClass();
   DexCache* dex_cache = declaring_class->GetDexCache();
   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
   const DexFile& dex_file = class_linker->FindDexFile(dex_cache);
-  const char* descriptor = dex_file.dexStringByTypeIdx(GetReturnTypeIdx());
+  const char* descriptor = dex_file.StringByTypeIdx(GetReturnTypeIdx());
   DCHECK(descriptor != NULL);
   return descriptor;
 }
@@ -504,24 +545,6 @@
   return num_registers;
 }
 
-size_t Method::NumArgArrayBytes() const {
-  const String* shorty = GetShorty();
-  size_t num_bytes = 0;
-  for (int i = 1; i < shorty->GetLength(); ++i) {
-    char ch = shorty->CharAt(i);
-    if (ch == 'D' || ch == 'J') {
-      num_bytes += 8;
-    } else if (ch == 'L') {
-      // Argument is a reference or an array.  The shorty descriptor
-      // does not distinguish between these types.
-      num_bytes += sizeof(Object*);
-    } else {
-      num_bytes += 4;
-    }
-  }
-  return num_bytes;
-}
-
 size_t Method::NumArgs() const {
   // "1 +" because the first in Args is the receiver.
   // "- 1" because we don't count the return type.
@@ -677,12 +700,11 @@
   const DexFile& dex_file = class_linker->FindDexFile(dex_cache);
   const DexFile::CodeItem* code_item = dex_file.GetCodeItem(GetCodeItemOffset());
   // Iterate over the catch handlers associated with dex_pc
-  for (DexFile::CatchHandlerIterator iter = dex_file.dexFindCatchHandler(*code_item, dex_pc);
-       !iter.HasNext(); iter.Next()) {
-    uint32_t iter_type_idx = iter.Get().type_idx_;
+  for (CatchHandlerIterator it(*code_item, dex_pc); it.HasNext(); it.Next()) {
+    uint16_t iter_type_idx = it.GetHandlerTypeIndex();
     // Catch all case
-    if (iter_type_idx == DexFile::kDexNoIndex) {
-      return iter.Get().address_;
+    if (iter_type_idx == DexFile::kDexNoIndex16) {
+      return it.GetHandlerAddress();
     }
     // Does this catch exception type apply?
     Class* iter_exception_type = dex_cache->GetResolvedType(iter_type_idx);
@@ -691,7 +713,7 @@
       LOG(WARNING) << "Unresolved exception class when finding catch block: "
           << dex_file.GetTypeDescriptor(dex_file.GetTypeId(iter_type_idx));
     } else if (iter_exception_type->IsAssignableFrom(exception_type)) {
-      return iter.Get().address_;
+      return it.GetHandlerAddress();
     }
   }
   // Handler not found
@@ -778,6 +800,11 @@
   return Heap::AllocObject(this, this->object_size_);
 }
 
+void Class::SetClassSize(size_t new_class_size) {
+  DCHECK_GE(new_class_size, GetClassSize()) << " class=" << PrettyTypeOf(this);
+  SetField32(OFFSET_OF_OBJECT_MEMBER(Class, class_size_), new_class_size, false);
+}
+
 void Class::DumpClass(std::ostream& os, int flags) const {
   if ((flags & kDumpClassFullDetail) == 0) {
     os << PrettyClass(this);
diff --git a/src/object.h b/src/object.h
index dd2c1ca..6a91970 100644
--- a/src/object.h
+++ b/src/object.h
@@ -619,6 +619,8 @@
     return (GetAccessFlags() & kAccSynthetic) != 0;
   }
 
+  uint32_t GetDexMethodIndex() const;
+
   uint16_t GetMethodIndex() const;
 
   size_t GetVtableIndex() const {
@@ -644,10 +646,6 @@
   // Number of 32bit registers that would be required to hold all the arguments
   static size_t NumArgRegisters(const StringPiece& shorty);
 
-  // Number of argument bytes required for densely packing the
-  // arguments into an array of arguments.
-  size_t NumArgArrayBytes() const;
-
   uint16_t NumRegisters() const;
 
   void SetNumRegisters(uint16_t new_num_registers) {
@@ -1088,7 +1086,8 @@
   // Native invocation stub entry point for calling from native to managed code.
   const InvokeStub* invoke_stub_;
 
-  // Index of the return type
+  // Index of the return type in the declaring classes dex cache or dex file's type ids
+  // TODO: value is really just 16bit
   uint32_t java_return_type_idx_;
 
   // Mapping from native pc to dex pc
@@ -1498,10 +1497,7 @@
     return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, class_size_), false);
   }
 
-  void SetClassSize(size_t new_class_size) {
-    DCHECK_GE(new_class_size, GetClassSize()) << " class=" << PrettyTypeOf(this);
-    SetField32(OFFSET_OF_OBJECT_MEMBER(Class, class_size_), new_class_size, false);
-  }
+  void SetClassSize(size_t new_class_size);
 
   size_t GetObjectSize() const {
     CHECK(!IsVariableSize()) << " class=" << PrettyTypeOf(this);
@@ -2092,9 +2088,11 @@
 
   // Set in LoadClass, used to LinkClass
   // see also super_class_
+  // TODO: really 16bits
   uint32_t super_class_type_idx_;
 
   // type index from dex file
+  // TODO: really 16bits
   uint32_t type_idx_;
 
   // TODO: ?
@@ -2199,15 +2197,6 @@
   return result;
 }
 
-inline void Field::SetOffset(MemberOffset num_bytes) {
-  DCHECK(GetDeclaringClass()->IsLoaded() || GetDeclaringClass()->IsErroneous());
-  Primitive::Type type = GetPrimitiveType();
-  if (type == Primitive::kPrimDouble || type == Primitive::kPrimLong) {
-    DCHECK_ALIGNED(num_bytes.Uint32Value(), 8);
-  }
-  SetField32(OFFSET_OF_OBJECT_MEMBER(Field, offset_), num_bytes.Uint32Value(), false);
-}
-
 inline Class* Field::GetDeclaringClass() const {
   Class* result = GetFieldObject<Class*>(OFFSET_OF_OBJECT_MEMBER(Field, declaring_class_), false);
   DCHECK(result != NULL);
@@ -2480,6 +2469,9 @@
 
   bool Equals(const String* that) const;
 
+  // Compare UTF-16 code point values not in a locale-sensitive manner
+  int Compare(int32_t utf16_length, const char* utf8_data_in);
+
   // TODO: do we need this overload? give it a more intention-revealing name.
   bool Equals(const uint16_t* that_chars, int32_t that_offset,
               int32_t that_length) const;
@@ -2615,7 +2607,7 @@
       this == String::GetJavaLangString() ||
       this == Field::GetJavaLangReflectField() ||
       this == Method::GetConstructorClass() ||
-      this == Method::GetMethodClass()) << PrettyClass(this);
+      this == Method::GetMethodClass());
   return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, access_flags_), false);
 }
 
diff --git a/src/runtime_support.cc b/src/runtime_support.cc
index 7ae5da5..e6011da 100644
--- a/src/runtime_support.cc
+++ b/src/runtime_support.cc
@@ -49,7 +49,7 @@
   /*
    * NOTE: once debugger/profiler support is added, we'll need to check
    * here and branch to actual compiled object.<init> to handle any
-   * breakpoint/logging activites if either is active.
+   * breakpoint/logging activities if either is active.
    */
   return self->IsExceptionPending() ? -1 : 0;
 }
@@ -163,7 +163,7 @@
     CHECK(false) << static_cast<int>(ref_type);
   }
 
-  std::string class_name(PrettyDescriptor(dex_file.dexStringByTypeIdx(type_idx)));
+  std::string class_name(PrettyDescriptor(dex_file.StringByTypeIdx(type_idx)));
   if (!access) {
     return class_name;
   }
@@ -185,7 +185,7 @@
 
   const DexFile::FieldId& id = dex_file.GetFieldId(ref);
   std::string class_name(PrettyDescriptor(dex_file.GetFieldDeclaringClassDescriptor(id)));
-  const char* field_name = dex_file.dexStringById(id.name_idx_);
+  const char* field_name = dex_file.StringDataByIdx(id.name_idx_);
   if (!access) {
     return class_name + "." + field_name;
   }
@@ -207,7 +207,7 @@
 
   const DexFile::MethodId& id = dex_file.GetMethodId(ref);
   std::string class_name(PrettyDescriptor(dex_file.GetMethodDeclaringClassDescriptor(id)));
-  const char* method_name = dex_file.dexStringById(id.name_idx_);
+  const char* method_name = dex_file.StringDataByIdx(id.name_idx_);
   if (!access) {
     return class_name + "." + method_name;
   }
@@ -215,7 +215,7 @@
   std::string result;
   result += "tried to access method ";
   result += class_name + "." + method_name + ":" +
-            dex_file.CreateMethodDescriptor(id.proto_idx_, NULL);
+      dex_file.CreateMethodSignature(id.proto_idx_, NULL);
   result += " from class ";
   result += PrettyDescriptor(method->GetDeclaringClass()->GetDescriptor());
   return result;
diff --git a/src/utf.cc b/src/utf.cc
index 31fbe97..52f03a9 100644
--- a/src/utf.cc
+++ b/src/utf.cc
@@ -87,6 +87,20 @@
   return ((one & 0x0f) << 12) | ((two & 0x3f) << 6) | (three & 0x3f);
 }
 
+int CompareModifiedUtf8ToModifiedUtf8AsUtf16CodePointValues(const char* utf8_1, const char* utf8_2) {
+  for (;;) {
+    uint16_t c1 = GetUtf16FromUtf8(&utf8_1);
+    uint16_t c2 = GetUtf16FromUtf8(&utf8_2);
+    if (c1 == 0) {
+      return (c2 == 0) ? 0 : -1;
+    } else if (c2 == 0) {
+      return 1;
+    } else if (c1 != c2) {
+      return c1 > c2 ? 1 : -1;
+    }
+  }
+}
+
 size_t CountUtf8Bytes(const uint16_t* chars, size_t char_count) {
   size_t result = 0;
   while (char_count--) {
diff --git a/src/utf.h b/src/utf.h
index 7b9b90e..42c6dc7 100644
--- a/src/utf.h
+++ b/src/utf.h
@@ -34,6 +34,11 @@
 void ConvertModifiedUtf8ToUtf16(uint16_t* utf16_out, const char* utf8_in);
 
 /*
+ * Compare two modified UTF-8 strings as UTF-16 code point values in a non-locale sensitive manner
+ */
+int CompareModifiedUtf8ToModifiedUtf8AsUtf16CodePointValues(const char* utf8_1, const char* utf8_2);
+
+/*
  * Convert from UTF-16 to Modified UTF-8. Note that the output is _not_
  * NUL-terminated. You probably need to call CountUtf8Bytes before calling
  * this anyway, so if you want a NUL-terminated string, you know where to
diff --git a/src/utils.cc b/src/utils.cc
index c37343c..c528f1c 100644
--- a/src/utils.cc
+++ b/src/utils.cc
@@ -153,6 +153,19 @@
   return result;
 }
 
+std::string PrettyMethod(uint32_t method_idx, const DexFile& dex_file, bool with_signature) {
+  const DexFile::MethodId& method_id = dex_file.GetMethodId(method_idx);
+  std::string result(PrettyDescriptor(dex_file.GetMethodDeclaringClassDescriptor(method_id)));
+  result += '.';
+  result += dex_file.GetMethodName(method_id);
+  if (with_signature) {
+    // TODO: iterate over the signature's elements and pass them all to
+    // PrettyDescriptor? We'd need to pull out the return type specially, too.
+    result += dex_file.GetMethodSignature(method_id);
+  }
+  return result;
+}
+
 std::string PrettyTypeOf(const Object* obj) {
   if (obj == NULL) {
     return "null";
diff --git a/src/utils.h b/src/utils.h
index f747ae8..f5e0c49 100644
--- a/src/utils.h
+++ b/src/utils.h
@@ -16,6 +16,7 @@
 namespace art {
 
 class Class;
+class DexFile;
 class Field;
 class Method;
 class Object;
@@ -166,6 +167,7 @@
 // Returns a human-readable signature for 'm'. Something like "a.b.C.m" or
 // "a.b.C.m(II)V" (depending on the value of 'with_signature').
 std::string PrettyMethod(const Method* m, bool with_signature = true);
+std::string PrettyMethod(uint32_t method_idx, const DexFile& dex_file, bool with_signature = true);
 
 // Returns a human-readable form of the name of the *class* of the given object.
 // So given an instance of java.lang.String, the output would
diff --git a/test/CreateMethodDescriptor/CreateMethodDescriptor.java b/test/CreateMethodDescriptor/CreateMethodDescriptor.java
deleted file mode 100644
index aa1f3de..0000000
--- a/test/CreateMethodDescriptor/CreateMethodDescriptor.java
+++ /dev/null
@@ -1,6 +0,0 @@
-// Copyright 2011 Google Inc. All Rights Reserved.
-
-class CreateMethodDescriptor {
-    Float m1(int a, double b, long c, Object d) { return null; }
-    CreateMethodDescriptor m2(boolean x, short y, char z) { return null; }
-}
diff --git a/test/CreateMethodSignature/CreateMethodSignature.java b/test/CreateMethodSignature/CreateMethodSignature.java
new file mode 100644
index 0000000..32338f1
--- /dev/null
+++ b/test/CreateMethodSignature/CreateMethodSignature.java
@@ -0,0 +1,6 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+
+class CreateMethodSignature {
+    Float m1(int a, double b, long c, Object d) { return null; }
+    CreateMethodSignature m2(boolean x, short y, char z) { return null; }
+}