Skip compilation of dead code from duplicate methods

Change-Id: If6114b3cd8e9a2d9a901dc93c352cee6afa3361f
diff --git a/src/compiler.cc b/src/compiler.cc
index ce1803c..cf37d6f 100644
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -1414,15 +1414,33 @@
     it.Next();
   }
   // Compile direct methods
+  uint32_t previous_direct_method_idx = 0;
   while (it.HasNextDirectMethod()) {
+    uint32_t method_idx = it.GetMemberIndex();
+    if (method_idx == previous_direct_method_idx) {
+      // smali can create dex files with two encoded_methods sharing the same method_idx
+      // http://code.google.com/p/smali/issues/detail?id=119
+      it.Next();
+      continue;
+    }
+    previous_direct_method_idx = method_idx;
     context->GetCompiler()->CompileMethod(it.GetMethodCodeItem(), it.GetMemberAccessFlags(),
-                                          it.GetMemberIndex(), class_loader, dex_file);
+                                          method_idx, class_loader, dex_file);
     it.Next();
   }
   // Compile virtual methods
+  uint32_t previous_virtual_method_idx = 0;
   while (it.HasNextVirtualMethod()) {
+    uint32_t method_idx = it.GetMemberIndex();
+    if (method_idx == previous_virtual_method_idx) {
+      // smali can create dex files with two encoded_methods sharing the same method_idx
+      // http://code.google.com/p/smali/issues/detail?id=119
+      it.Next();
+      continue;
+    }
+    previous_virtual_method_idx = method_idx;
     context->GetCompiler()->CompileMethod(it.GetMethodCodeItem(), it.GetMemberAccessFlags(),
-                                          it.GetMemberIndex(), class_loader, dex_file);
+                                          method_idx, class_loader, dex_file);
     it.Next();
   }
   DCHECK(!it.HasNext());
diff --git a/src/dex_file.cc b/src/dex_file.cc
index eb2a157..eb48ded 100644
--- a/src/dex_file.cc
+++ b/src/dex_file.cc
@@ -824,12 +824,20 @@
 void ClassDataItemIterator::ReadClassDataField() {
   field_.field_idx_delta_ = DecodeUnsignedLeb128(&ptr_pos_);
   field_.access_flags_ = DecodeUnsignedLeb128(&ptr_pos_);
+  if (field_.field_idx_delta_ == 0) {
+    LOG(WARNING) << "Duplicate field " << PrettyField(GetMemberIndex(), dex_file_)
+                 << " in " << dex_file_.GetLocation();
+  }
 }
 
 void ClassDataItemIterator::ReadClassDataMethod() {
   method_.method_idx_delta_ = DecodeUnsignedLeb128(&ptr_pos_);
   method_.access_flags_ = DecodeUnsignedLeb128(&ptr_pos_);
   method_.code_off_ = DecodeUnsignedLeb128(&ptr_pos_);
+  if (method_.method_idx_delta_ == 0) {
+    LOG(WARNING) << "Duplicate method " << PrettyMethod(GetMemberIndex(), dex_file_)
+                 << " in " << dex_file_.GetLocation();
+  }
 }
 
 // Read a signed integer.  "zwidth" is the zero-based byte count.
diff --git a/src/utils.cc b/src/utils.cc
index 629d513..4e35cd2 100644
--- a/src/utils.cc
+++ b/src/utils.cc
@@ -257,6 +257,19 @@
   return result;
 }
 
+std::string PrettyField(uint32_t field_idx, const DexFile& dex_file, bool with_type) {
+  const DexFile::FieldId& field_id = dex_file.GetFieldId(field_idx);
+  std::string result;
+  if (with_type) {
+    result += dex_file.GetFieldTypeDescriptor(field_id);
+    result += ' ';
+  }
+  result += PrettyDescriptor(dex_file.GetFieldDeclaringClassDescriptor(field_id));
+  result += '.';
+  result += dex_file.GetFieldName(field_id);
+  return result;
+}
+
 std::string PrettyArguments(const char* signature) {
   std::string result;
   result += '(';
diff --git a/src/utils.h b/src/utils.h
index 8e19ced..a26358a 100644
--- a/src/utils.h
+++ b/src/utils.h
@@ -172,6 +172,7 @@
 // Returns a human-readable signature for 'f'. Something like "a.b.C.f" or
 // "int a.b.C.f" (depending on the value of 'with_type').
 std::string PrettyField(const Field* f, bool with_type = true);
+std::string PrettyField(uint32_t field_idx, const DexFile& dex_file, bool with_type = true);
 
 // 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').