Several fixes for proper creation and use of vmap tables
Change-Id: I7696115af4263df18ede0777ae14de7a3a7ada3b
diff --git a/src/thread.cc b/src/thread.cc
index b8dbd6b..e45da0d 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -1359,7 +1359,8 @@
Method* m = frame.GetMethod();
if (false) {
LOG(INFO) << "Visiting stack roots in " << PrettyMethod(m, false)
- << "@ PC: " << m->ToDexPC(pc);
+ << StringPrintf("@ PC:%04x", m->ToDexPC(pc));
+
}
// Process register map (which native and callee save methods don't have)
if (!m->IsNative() && !m->IsCalleeSaveMethod()) {
@@ -1367,8 +1368,9 @@
const uint8_t* reg_bitmap = map.FindBitMap(m->ToDexPC(pc));
CHECK(reg_bitmap != NULL);
const uint16_t* vmap = m->GetVmapTable();
- // For all dex registers
- for (int reg = 0; reg < m->NumRegisters(); ++reg) {
+ // For all dex registers in the bitmap
+ size_t num_regs = std::min(map.RegWidth() * 8, static_cast<size_t>(m->NumRegisters()));
+ for (size_t reg = 0; reg < num_regs; ++reg) {
// Does this register hold a reference?
if (TestBitmap(reg, reg_bitmap)) {
// Is the reference in the context or on the stack?
@@ -1376,6 +1378,10 @@
uint32_t vmap_offset = 0xEBAD0FF5;
// TODO: take advantage of the registers being ordered
for (int i = 0; i < m->GetVmapTableLength(); i++) {
+ // stop if we find what we are are looking for or the INVALID_VREG that marks lr
+ if (vmap[i] == 0xffff) {
+ break;
+ }
if (vmap[i] == reg) {
in_context = true;
vmap_offset = i;
@@ -1386,10 +1392,11 @@
if (in_context) {
// Compute the register we need to load from the context
uint32_t spill_mask = m->GetCoreSpillMask();
+ CHECK_LT(vmap_offset, static_cast<uint32_t>(__builtin_popcount(spill_mask)));
uint32_t matches = 0;
uint32_t spill_shifts = 0;
while (matches != (vmap_offset + 1)) {
- CHECK_NE(spill_mask, 0u);
+ DCHECK_NE(spill_mask, 0u);
matches += spill_mask & 1; // Add 1 if the low bit is set
spill_mask >>= 1;
spill_shifts++;