summaryrefslogtreecommitdiffstats
path: root/test/StackWalk
diff options
context:
space:
mode:
authorIan Rogers <irogers@google.com>2011-10-03 13:57:23 -0700
committerIan Rogers <irogers@google.com>2011-10-24 11:56:15 -0700
commitd81871cbbaa34c649e488f94f61a981db33123e5 (patch)
treea3adf3b7469fee507a4d4c4491942fbd48b4483d /test/StackWalk
parent262bf46ddc91e5b4fbd367127ff21a1877d939f2 (diff)
downloadart-d81871cbbaa34c649e488f94f61a981db33123e5.zip
art-d81871cbbaa34c649e488f94f61a981db33123e5.tar.gz
art-d81871cbbaa34c649e488f94f61a981db33123e5.tar.bz2
Verifier clean up.
This is the first part in trying to move to a more rigorous mode of asserting the validity of garbage collection maps. In the bring over of the verifier from Dalvik a large class had been created where all of the Dalvik/Dex functions were static methods of that class. This rewrite introduces 3 key classes, Verifier that orchestrates the verification of a method, RegisterLine which describes the types associated with registers for a particular PC and RegType which describes the current type of a register within a line. The functionality is brought over from Dalvik but cleaned up to not do things like goto. Failing within the verifier is also cleaned up. By virtue of having stateful objects the interfaces between different aspects of the verifier are greatly simplified. To save space, RegTypes are cached upto a maximum possible 2^16, and given an Id. As the number of RegTypes is typically small this means that we have a full OO implementation but at a lower space cost than the current convention that uses botched together enum values requiring 32bits of storage in a RegisterLine rather than 16bits (ie half the space requirement per register in a register line). To make use of this space more rigorous monitor verification is brought back, and ultimately I think we can work around bug 3215458 with richer RegTypes that are aware of literal objects. The code removes short cuts that had been added to Dalvik's verifier and appear illegitimate, it also fixes a large number of bugs in the description of the verifier. Where possible the spaghetti of code is replaced with straight line if-then-elsif.. code that clearly follows the ordering semantics of the specification. The code is also aiming toward having a more type rigorous description of the verification process, and when this isn't possible following the description convention of the specification. Change-Id: Id25b742018a2ad5ea95687973cca610d7e19513c
Diffstat (limited to 'test/StackWalk')
-rw-r--r--test/StackWalk/stack_walk_jni.cc36
1 files changed, 13 insertions, 23 deletions
diff --git a/test/StackWalk/stack_walk_jni.cc b/test/StackWalk/stack_walk_jni.cc
index 5e4a8a2..6a23d1f 100644
--- a/test/StackWalk/stack_walk_jni.cc
+++ b/test/StackWalk/stack_walk_jni.cc
@@ -10,15 +10,15 @@
namespace art {
-#define REG(method, reg_vector, reg) \
+#define REG(method, reg_bitmap, reg) \
( ((reg) < (method)->NumRegisters()) && \
- (( *((reg_vector) + (reg)/8) >> ((reg) % 8) ) & 0x01) )
+ (( *((reg_bitmap) + (reg)/8) >> ((reg) % 8) ) & 0x01) )
#define CHECK_REGS(...) do { \
int t[] = {__VA_ARGS__}; \
int t_size = sizeof(t) / sizeof(*t); \
for (int i = 0; i < t_size; ++i) \
- CHECK(REG(m, reg_vector, t[i])) << "Error: Reg " << i << " is not in RegisterMap"; \
+ CHECK(REG(m, reg_bitmap, t[i])) << "Error: Reg " << i << " is not in RegisterMap"; \
} while(false)
static int gJava_StackWalk_refmap_calls = 0;
@@ -29,31 +29,22 @@ struct ReferenceMapVisitor : public Thread::StackVisitor {
void VisitFrame(const Frame& frame, uintptr_t pc) {
Method* m = frame.GetMethod();
- if (!m ||m->IsNative()) {
- return;
- }
+ CHECK(m != NULL);
LOG(INFO) << "At " << PrettyMethod(m, false);
- art::DexVerifier::RegisterMap* map = new art::DexVerifier::RegisterMap(
- m->GetRegisterMapHeader(),
- m->GetRegisterMapData());
-
- if (!pc) {
- // pc == NULL: m is either a native method or a phony method
- return;
- }
- if (m->IsCalleeSaveMethod()) {
+ if (m->IsCalleeSaveMethod() || m->IsNative()) {
LOG(WARNING) << "no PC for " << PrettyMethod(m);
+ CHECK_EQ(pc, 0u);
return;
}
-
- const uint8_t* reg_vector = art::DexVerifier::RegisterMapGetLine(map, m->ToDexPC(pc));
- std::string m_name = m->GetName()->ToModifiedUtf8();
+ verifier::PcToReferenceMap map(m);
+ const uint8_t* reg_bitmap = map.FindBitMap(m->ToDexPC(pc));
+ String* m_name = m->GetName();
// Given the method name and the number of times the method has been called,
// we know the Dex registers with live reference values. Assert that what we
// find is what is expected.
- if (m_name.compare("f") == 0) {
+ if (m_name->Equals("f") == 0) {
if (gJava_StackWalk_refmap_calls == 1) {
CHECK_EQ(1U, m->ToDexPC(pc));
CHECK_REGS(1);
@@ -62,7 +53,7 @@ struct ReferenceMapVisitor : public Thread::StackVisitor {
CHECK_EQ(5U, m->ToDexPC(pc));
CHECK_REGS(1);
}
- } else if (m_name.compare("g") == 0) {
+ } else if (m_name->Equals("g") == 0) {
if (gJava_StackWalk_refmap_calls == 1) {
CHECK_EQ(0xcU, m->ToDexPC(pc));
CHECK_REGS(0, 2); // Note that v1 is not in the minimal root set
@@ -71,7 +62,7 @@ struct ReferenceMapVisitor : public Thread::StackVisitor {
CHECK_EQ(0xcU, m->ToDexPC(pc));
CHECK_REGS(0, 2);
}
- } else if (m_name.compare("shlemiel") == 0) {
+ } else if (m_name->Equals("shlemiel") == 0) {
if (gJava_StackWalk_refmap_calls == 1) {
CHECK_EQ(0x380U, m->ToDexPC(pc));
CHECK_REGS(2, 4, 5, 7, 8, 9, 10, 11, 13, 14, 15, 16, 17, 18, 19, 21, 25);
@@ -81,8 +72,7 @@ struct ReferenceMapVisitor : public Thread::StackVisitor {
CHECK_REGS(2, 4, 5, 7, 8, 9, 10, 11, 13, 14, 15, 16, 17, 18, 19, 21, 25);
}
}
-
- LOG(INFO) << reg_vector;
+ LOG(INFO) << reg_bitmap;
}
};