Make stack visitor location for bad roots more verbose.
Change-Id: Ib2f3f48ccf1f5b2f3a4d1a61df553ad1a5c29d38
diff --git a/src/gc/mark_sweep.cc b/src/gc/mark_sweep.cc
index 1ccceaa..e0ecc99 100644
--- a/src/gc/mark_sweep.cc
+++ b/src/gc/mark_sweep.cc
@@ -260,19 +260,18 @@
}
void MarkSweep::VerifyRootCallback(const Object* root, void* arg, size_t vreg,
- const AbstractMethod* method) {
- reinterpret_cast<MarkSweep*>(arg)->VerifyRoot(root, vreg, method);
+ const StackVisitor* visitor) {
+ reinterpret_cast<MarkSweep*>(arg)->VerifyRoot(root, vreg, visitor);
}
-void MarkSweep::VerifyRoot(const Object* root, size_t vreg, const AbstractMethod* method) {
+void MarkSweep::VerifyRoot(const Object* root, size_t vreg, const StackVisitor* visitor) {
// See if the root is on any space bitmap.
if (GetHeap()->GetLiveBitmap()->GetSpaceBitmap(root) == NULL) {
LargeObjectSpace* large_object_space = GetHeap()->GetLargeObjectsSpace();
if (!large_object_space->Contains(root)) {
LOG(ERROR) << "Found invalid root: " << root;
- LOG(ERROR) << "VReg: " << vreg;
- if (method != NULL) {
- LOG(ERROR) << "In method " << PrettyMethod(method, true);
+ if (visitor != NULL) {
+ LOG(ERROR) << visitor->DescribeLocation() << " in VReg: " << vreg;
}
}
}
diff --git a/src/gc/mark_sweep.h b/src/gc/mark_sweep.h
index 98445d4..0fee24f 100644
--- a/src/gc/mark_sweep.h
+++ b/src/gc/mark_sweep.h
@@ -295,9 +295,9 @@
void ExpandMarkStack();
static void VerifyRootCallback(const Object* root, void* arg, size_t vreg,
- const AbstractMethod* method);
+ const StackVisitor *visitor);
- void VerifyRoot(const Object* root, size_t vreg, const AbstractMethod* method)
+ void VerifyRoot(const Object* root, size_t vreg, const StackVisitor* visitor)
NO_THREAD_SAFETY_ANALYSIS;
template <typename Visitor>
diff --git a/src/heap.h b/src/heap.h
index 22b009c..67d8c05 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -53,6 +53,7 @@
class Object;
class Space;
class SpaceTest;
+class StackVisitor;
class Thread;
class TimingLogger;
@@ -107,7 +108,7 @@
typedef void (RootVisitor)(const Object* root, void* arg);
typedef void (VerifyRootVisitor)(const Object* root, void* arg, size_t vreg,
- const AbstractMethod* method);
+ const StackVisitor* visitor);
typedef bool (IsMarkedTester)(const Object* object, void* arg);
// Create a heap with the requested sizes. The possible empty
diff --git a/src/stack.cc b/src/stack.cc
index f712652..be737ac 100644
--- a/src/stack.cc
+++ b/src/stack.cc
@@ -149,6 +149,16 @@
return visitor.frames;
}
+std::string StackVisitor::DescribeLocation() const {
+ std::string result("Visiting method '");
+ result += PrettyMethod(GetMethod());
+ result += StringPrintf("' at dex PC 0x%04zx", GetDexPc());
+ if (!IsShadowFrame()) {
+ result += StringPrintf(" (native PC %p)", reinterpret_cast<void*>(GetCurrentQuickFramePc()));
+ }
+ return result;
+}
+
void StackVisitor::SanityCheckFrame() const {
#ifndef NDEBUG
AbstractMethod* method = GetMethod();
diff --git a/src/stack.h b/src/stack.h
index 5b5609c..1dfd5b6 100644
--- a/src/stack.h
+++ b/src/stack.h
@@ -25,6 +25,7 @@
#include "oat/runtime/context.h"
#include <stdint.h>
+#include <string>
namespace art {
@@ -477,6 +478,8 @@
return reinterpret_cast<StackIndirectReferenceTable*>(sp);
}
+ std::string DescribeLocation() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
private:
size_t ComputeNumFrames() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
diff --git a/src/thread.cc b/src/thread.cc
index 943fdcb..744a8aa 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -1838,12 +1838,12 @@
return object->GetThinLockId() == thin_lock_id_;
}
-// Visitor parameters are: (const Object* obj, size_t vreg, const AbstractMethod* method).
-template <typename Visitor>
+// RootVisitor parameters are: (const Object* obj, size_t vreg, const StackVisitor* visitor).
+template <typename RootVisitor>
class ReferenceMapVisitor : public StackVisitor {
public:
ReferenceMapVisitor(const ManagedStack* stack, const std::vector<InstrumentationStackFrame>* instrumentation_stack,
- Context* context, const Visitor& visitor)
+ Context* context, const RootVisitor& visitor)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
: StackVisitor(stack, instrumentation_stack, context), visitor_(visitor) {}
@@ -1854,7 +1854,7 @@
}
ShadowFrame* shadow_frame = GetCurrentShadowFrame();
if (shadow_frame != NULL) {
- WrapperVisitor wrapperVisitor(visitor_, shadow_frame->GetMethod());
+ WrapperVisitor wrapperVisitor(visitor_, this);
shadow_frame->VisitRoots(wrapperVisitor);
} else {
AbstractMethod* m = GetMethod();
@@ -1893,7 +1893,7 @@
}
if (ref != NULL) {
- visitor_(ref, reg, m);
+ visitor_(ref, reg, this);
}
}
}
@@ -1907,19 +1907,16 @@
class WrapperVisitor {
public:
- WrapperVisitor(const Visitor& visitor, AbstractMethod* method)
- : visitor_(visitor),
- method_(method) {
-
- }
+ WrapperVisitor(const RootVisitor& root_visitor, const StackVisitor* stack_visitor)
+ : root_visitor_(root_visitor), stack_visitor_(stack_visitor) {}
void operator()(const Object* obj, size_t offset) const {
- visitor_(obj, offset, method_);
+ root_visitor_(obj, offset, stack_visitor_);
}
private:
- const Visitor& visitor_;
- AbstractMethod* method_;
+ const RootVisitor& root_visitor_;
+ const StackVisitor* const stack_visitor_;
};
static bool TestBitmap(int reg, const uint8_t* reg_vector) {
@@ -1927,7 +1924,7 @@
}
// Visitor for when we visit a root.
- const Visitor& visitor_;
+ const RootVisitor& visitor_;
// A method helper we keep around to avoid dex file/cache re-computations.
MethodHelper mh_;
@@ -1939,7 +1936,7 @@
}
- void operator()(const Object* obj, size_t, const AbstractMethod*) const {
+ void operator()(const Object* obj, size_t, const StackVisitor*) const {
visitor_(obj, arg_);
}
@@ -1953,16 +1950,15 @@
VerifyCallbackVisitor(Heap::VerifyRootVisitor* visitor, void* arg)
: visitor_(visitor),
arg_(arg) {
-
}
- void operator()(const Object* obj, size_t vreg, const AbstractMethod* method) const {
- visitor_(obj, arg_, vreg, method);
+ void operator()(const Object* obj, size_t vreg, const StackVisitor* visitor) const {
+ visitor_(obj, arg_, vreg, visitor);
}
private:
- Heap::VerifyRootVisitor* visitor_;
- void* arg_;
+ Heap::VerifyRootVisitor* const visitor_;
+ void* const arg_;
};
struct VerifyRootWrapperArg {