Various things.

Change-Id: I6911c995d7635b95e6dc6b9112bf4e1adf85e830
diff --git a/src/class_linker.cc b/src/class_linker.cc
index 514a061..2c683e9 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -1415,7 +1415,9 @@
       const Method* method = super->GetVirtualMethod(i);
       if (method != super->GetVirtualMethod(i) &&
           !HasSameMethodDescriptorClasses(method, super, klass)) {
-        ThrowLinkageError("Classes resolve differently in superclass");
+        klass->DumpClass(std::cerr, Class::kDumpClassFullDetail);
+
+        ThrowLinkageError("Class %s method %s resolves differently in superclass %s", PrettyDescriptor(klass->GetDescriptor()).c_str(), PrettyMethod(method).c_str(), PrettyDescriptor(super->GetDescriptor()).c_str());
         return false;
       }
     }
@@ -1428,7 +1430,9 @@
         const Method* method = interface_entry->GetMethodArray()->Get(j);
         if (!HasSameMethodDescriptorClasses(method, interface,
                                             method->GetDeclaringClass())) {
-          ThrowLinkageError("Classes resolve differently in interface");
+          klass->DumpClass(std::cerr, Class::kDumpClassFullDetail);
+
+          ThrowLinkageError("Class %s method %s resolves differently in interface %s", PrettyDescriptor(method->GetDeclaringClass()->GetDescriptor()).c_str(), PrettyMethod(method).c_str(), PrettyDescriptor(interface->GetDescriptor()).c_str());
           return false;
         }
       }
@@ -1440,6 +1444,7 @@
 bool ClassLinker::HasSameMethodDescriptorClasses(const Method* method,
                                                  const Class* klass1,
                                                  const Class* klass2) {
+  if (method->IsMiranda()) { return true; }
   const DexFile& dex_file = FindDexFile(method->GetDeclaringClass()->GetDexCache());
   const DexFile::ProtoId& proto_id = dex_file.GetProtoId(method->GetProtoIdx());
   DexFile::ParameterIterator *it;
@@ -1523,6 +1528,8 @@
   }
 
   Thread* self = Thread::Current();
+  ScopedThreadStateChange tsc(self, Thread::kRunnable);
+  LOG(INFO) << "initializing " << PrettyClass(c) << " from " << *self;
   c->MonitorEnter(self);
   InitializeClass(c, can_run_clinit);
   c->MonitorExit(self);
@@ -1818,8 +1825,6 @@
 }
 
 bool ClassLinker::LinkInterfaceMethods(Class* klass) {
-  int miranda_count = 0;
-  int miranda_alloc = 0;
   size_t super_ifcount;
   if (klass->HasSuperClass()) {
     super_ifcount = klass->GetSuperClass()->GetIfTableCount();
@@ -1856,14 +1861,18 @@
           PrettyDescriptor(interface->GetDescriptor()).c_str());
       return false;
     }
+    // Add this interface.
     iftable->Set(idx++, AllocInterfaceEntry(interface));
+    // Add this interface's superinterfaces.
     for (int32_t j = 0; j < interface->GetIfTableCount(); j++) {
       iftable->Set(idx++, AllocInterfaceEntry(interface->GetIfTable()->Get(j)->GetInterface()));
     }
   }
   klass->SetIfTable(iftable);
   CHECK_EQ(idx, ifcount);
-  if (klass->IsInterface()) {
+
+  // If we're an interface, we don't need the vtable pointers, so we're done.
+  if (klass->IsInterface() /*|| super_ifcount == ifcount*/) {
     return true;
   }
   std::vector<Method*> miranda_list;
@@ -1876,6 +1885,14 @@
     for (size_t j = 0; j < interface->NumVirtualMethods(); ++j) {
       Method* interface_method = interface->GetVirtualMethod(j);
       int32_t k;
+      // For each method listed in the interface's method list, find the
+      // matching method in our class's method list.  We want to favor the
+      // subclass over the superclass, which just requires walking
+      // back from the end of the vtable.  (This only matters if the
+      // superclass defines a private method and this class redefines
+      // it -- otherwise it would use the same vtable slot.  In .dex files
+      // those don't end up in the virtual method table, so it shouldn't
+      // matter which direction we go.  We walk it backward anyway.)
       for (k = vtable->GetLength() - 1; k >= 0; --k) {
         Method* vtable_method = vtable->Get(k);
         if (interface_method->HasSameNameAndDescriptor(vtable_method)) {
@@ -1889,33 +1906,26 @@
         }
       }
       if (k < 0) {
-        if (miranda_count == miranda_alloc) {
-          miranda_alloc += 8;
-          if (miranda_list.empty()) {
-            miranda_list.resize(miranda_alloc);
-          } else {
-            miranda_list.resize(miranda_alloc);
-          }
-        }
         Method* miranda_method = NULL;
-        int mir;
-        for (mir = 0; mir < miranda_count; mir++) {
-          miranda_method = miranda_list[mir];
-          if (miranda_method->HasSameNameAndDescriptor(interface_method)) {
+        for (size_t mir = 0; mir < miranda_list.size(); mir++) {
+          if (miranda_list[mir]->HasSameNameAndDescriptor(interface_method)) {
+            miranda_method = miranda_list[mir];
             break;
           }
         }
-        // point the interface table at a phantom slot
-        method_array->Set(j, miranda_method);
-        if (mir == miranda_count) {
-          miranda_list[miranda_count++] = interface_method;
+        if (miranda_method == NULL) {
+          // point the interface table at a phantom slot
+          miranda_method = AllocMethod();
+          memcpy(miranda_method, interface_method, sizeof(Method));
+          miranda_list.push_back(miranda_method);
         }
+        method_array->Set(j, miranda_method);
       }
     }
   }
-  if (miranda_count != 0) {
+  if (!miranda_list.empty()) {
     int old_method_count = klass->NumVirtualMethods();
-    int new_method_count = old_method_count + miranda_count;
+    int new_method_count = old_method_count + miranda_list.size();
     klass->SetVirtualMethods((old_method_count == 0)
                              ? AllocObjectArray<Method>(new_method_count)
                              : klass->GetVirtualMethods()->CopyOf(new_method_count));
@@ -1923,12 +1933,12 @@
     ObjectArray<Method>* vtable = klass->GetVTableDuringLinking();
     CHECK(vtable != NULL);
     int old_vtable_count = vtable->GetLength();
-    int new_vtable_count = old_vtable_count + miranda_count;
+    int new_vtable_count = old_vtable_count + miranda_list.size();
     vtable = vtable->CopyOf(new_vtable_count);
-    for (int i = 0; i < miranda_count; i++) {
-      Method* meth = AllocMethod();
+    for (size_t i = 0; i < miranda_list.size(); ++i) {
+      Method* meth = miranda_list[i]; //AllocMethod();
       // TODO: this shouldn't be a memcpy
-      memcpy(meth, miranda_list[i], sizeof(Method));
+      //memcpy(meth, miranda_list[i], sizeof(Method));
       meth->SetDeclaringClass(klass);
       meth->SetAccessFlags(meth->GetAccessFlags() | kAccMiranda);
       meth->SetMethodIndex(0xFFFF & (old_vtable_count + i));
@@ -1938,6 +1948,14 @@
     // TODO: do not assign to the vtable field until it is fully constructed.
     klass->SetVTable(vtable);
   }
+
+  ObjectArray<Method>* vtable = klass->GetVTableDuringLinking();
+  for (int i = 0; i < vtable->GetLength(); ++i) {
+    CHECK(vtable->Get(i) != NULL);
+  }
+
+//  klass->DumpClass(std::cerr, Class::kDumpClassFullDetail);
+
   return true;
 }
 
diff --git a/src/monitor.cc b/src/monitor.cc
index 0ef5fb4..7d6cde4 100644
--- a/src/monitor.cc
+++ b/src/monitor.cc
@@ -188,8 +188,8 @@
   Monitor handle;
   Monitor *curr;
 
-  assert(mon != NULL);
-  assert(isUnmarkedObject != NULL);
+  DCHECK(mon != NULL);
+  DCHECK(isUnmarkedObject != NULL);
   Monitor* prev = &handle;
   prev->next = curr = *mon;
   while (curr != NULL) {
@@ -660,8 +660,8 @@
   long maxSleepDelayNs = 1000000000;  /* 1 second */
   uint32_t thin, newThin, threadId;
 
-  assert(self != NULL);
-  assert(obj != NULL);
+  DCHECK(self != NULL);
+  DCHECK(obj != NULL);
   threadId = self->thin_lock_id_;
 retry:
   thin = *thinp;
@@ -749,6 +749,7 @@
     }
   } else {
     // The lock is a fat lock.
+    LOG(INFO) << StringPrintf("(%d) locking fat lock %p (%p) %p on a %s", threadId, thinp, LW_MONITOR(*thinp), (void*)*thinp, PrettyTypeOf(obj).c_str());
     DCHECK(LW_MONITOR(*thinp) != NULL);
     LW_MONITOR(*thinp)->Lock(self);
   }
@@ -758,7 +759,7 @@
   volatile int32_t* thinp = obj->GetRawLockWordAddress();
 
   DCHECK(self != NULL);
-  DCHECK_EQ(self->GetState(), Thread::kRunnable);
+  //DCHECK_EQ(self->GetState(), Thread::kRunnable);
   DCHECK(obj != NULL);
 
   /*
diff --git a/src/object.cc b/src/object.cc
index ff49ad3..e37b683 100644
--- a/src/object.cc
+++ b/src/object.cc
@@ -688,7 +688,10 @@
 
 void Method::SetCode(ByteArray* code_array, InstructionSet instruction_set,
                      IntArray* mapping_table, ShortArray* vmap_table) {
-  CHECK(GetCode() == NULL || IsNative());
+//  CHECK(GetCode() == NULL || IsNative()) << PrettyMethod(this);
+  if (GetCode() != NULL && !IsNative()) {
+    LOG(WARNING) << "Calling SetCode more than once for " << PrettyMethod(this);
+  }
   SetFieldPtr<ByteArray*>(OFFSET_OF_OBJECT_MEMBER(Method, code_array_), code_array, false);
   SetFieldPtr<IntArray*>(OFFSET_OF_OBJECT_MEMBER(Method, mapping_table_),
        mapping_table, false);
@@ -807,7 +810,7 @@
   return Heap::AllocObject(this, this->object_size_);
 }
 
-void Class::DumpClass(std::ostream& os, int flags) {
+void Class::DumpClass(std::ostream& os, int flags) const {
   if ((flags & kDumpClassFullDetail) == 0) {
     os << PrettyClass(this);
     if ((flags & kDumpClassClassLoader) != 0) {
@@ -844,7 +847,7 @@
   os << "  vtable (" << NumVirtualMethods() << " entries, "
      << (super != NULL ? super->NumVirtualMethods() : 0) << " in super):\n";
   for (size_t i = 0; i < NumVirtualMethods(); ++i) {
-    os << StringPrintf("    %2d: %s\n", i, PrettyMethod(GetVirtualMethod(i)).c_str());
+    os << StringPrintf("    %2d: %s\n", i, PrettyMethod(GetVirtualMethodDuringLinking(i)).c_str());
   }
   os << "  direct methods (" << NumDirectMethods() << " entries):\n";
   for (size_t i = 0; i < NumDirectMethods(); ++i) {
@@ -852,14 +855,22 @@
   }
   if (NumStaticFields() > 0) {
     os << "  static fields (" << NumStaticFields() << " entries):\n";
-    for (size_t i = 0; i < NumStaticFields(); ++i) {
-      os << StringPrintf("    %2d: %s\n", i, PrettyField(GetStaticField(i)).c_str());
+    if (IsLoaded() || IsErroneous()) {
+      for (size_t i = 0; i < NumStaticFields(); ++i) {
+//        os << StringPrintf("    %2d: %s\n", i, PrettyField(GetStaticField(i)).c_str());
+      }
+    } else {
+      os << "    <not yet available>";
     }
   }
   if (NumInstanceFields() > 0) {
     os << "  instance fields (" << NumInstanceFields() << " entries):\n";
-    for (size_t i = 0; i < NumInstanceFields(); ++i) {
-      os << StringPrintf("    %2d: %s\n", i, PrettyField(GetInstanceField(i)).c_str());
+    if (IsLoaded() || IsErroneous()) {
+      for (size_t i = 0; i < NumInstanceFields(); ++i) {
+//        os << StringPrintf("    %2d: %s\n", i, PrettyField(GetInstanceField(i)).c_str());
+      }
+    } else {
+      os << "    <not yet available>";
     }
   }
 }
diff --git a/src/object.h b/src/object.h
index e94671b..2ceafbd 100644
--- a/src/object.h
+++ b/src/object.h
@@ -1600,7 +1600,7 @@
     kDumpClassInitialized = (1 << 2),
   };
 
-  void DumpClass(std::ostream& os, int flags);
+  void DumpClass(std::ostream& os, int flags) const;
 
   DexCache* GetDexCache() const;