diff options
| -rw-r--r-- | src/class_linker.cc | 72 | ||||
| -rw-r--r-- | src/monitor.cc | 11 | ||||
| -rw-r--r-- | src/object.cc | 25 | ||||
| -rw-r--r-- | src/object.h | 2 |
4 files changed, 70 insertions, 40 deletions
diff --git a/src/class_linker.cc b/src/class_linker.cc index 514a061703..2c683e902c 100644 --- a/src/class_linker.cc +++ b/src/class_linker.cc @@ -1415,7 +1415,9 @@ bool ClassLinker::ValidateSuperClassDescriptors(const Class* klass) { 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 @@ bool ClassLinker::ValidateSuperClassDescriptors(const Class* klass) { 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::ValidateSuperClassDescriptors(const Class* klass) { 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 @@ bool ClassLinker::EnsureInitialized(Class* c, bool can_run_clinit) { } 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::LinkVirtualMethods(Class* klass) { } 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 @@ bool ClassLinker::LinkInterfaceMethods(Class* klass) { 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 @@ bool ClassLinker::LinkInterfaceMethods(Class* klass) { 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 @@ bool ClassLinker::LinkInterfaceMethods(Class* klass) { } } 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 @@ bool ClassLinker::LinkInterfaceMethods(Class* klass) { 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 @@ bool ClassLinker::LinkInterfaceMethods(Class* klass) { // 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 0ef5fb42e9..7d6cde4c73 100644 --- a/src/monitor.cc +++ b/src/monitor.cc @@ -188,8 +188,8 @@ static void SweepMonitorList(Monitor** mon, bool (isUnmarkedObject)(void*)) { 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 @@ void Monitor::MonitorEnter(Thread* self, Object* obj) { 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 @@ retry: } } 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 @@ bool Monitor::MonitorExit(Thread* self, Object* obj) { 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 ff49ad3ac6..e37b68312d 100644 --- a/src/object.cc +++ b/src/object.cc @@ -688,7 +688,10 @@ uint32_t Method::FindCatchBlock(Class* exception_type, uint32_t dex_pc) const { 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 @@ Object* Class::AllocObject() { 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 @@ void Class::DumpClass(std::ostream& os, int flags) { 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 @@ void Class::DumpClass(std::ostream& os, int flags) { } 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 e94671ba1e..2ceafbdd2c 100644 --- a/src/object.h +++ b/src/object.h @@ -1600,7 +1600,7 @@ class MANAGED Class : public StaticStorageBase { kDumpClassInitialized = (1 << 2), }; - void DumpClass(std::ostream& os, int flags); + void DumpClass(std::ostream& os, int flags) const; DexCache* GetDexCache() const; |