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;