iterator.setupIterator(compiledMethod, offset.toInt(), fp);
iterator.setupIterator(compiledMethod, offset, fp);
  private static void scanThreadInternal(AddressDeque rootLocations,                                          AddressPairDeque codeLocations,                                         VM_Thread t, Address top_frame) {        if (DUMP_STACK >= 1) VM.sysWriteln("Scanning thread ", t.getIndex());    // Don't forget ip in hardwareExceptionRegisters, if it is in use.    //    if (codeLocations != null && t.hardwareExceptionRegisters.inuse) {      Address ip = t.hardwareExceptionRegisters.ip;      VM_CompiledMethod compiledMethod = VM_CompiledMethods.findMethodForInstruction(ip);      if (VM.VerifyAssertions) VM._assert(compiledMethod != null);      compiledMethod.setObsolete( false );      ObjectReference code = ObjectReference.fromObject(compiledMethod.getInstructions());      Address ipLoc = t.hardwareExceptionRegisters.getIPLocation();      codeLocationsPush(codeLocations, code, ipLoc, 1, t);    }    // get gc thread local iterator group from our VM_CollectorThread object    //    VM_CollectorThread collector = VM_Magic.threadAsCollectorThread(VM_Thread.getCurrentThread());    VM_GCMapIteratorGroup iteratorGroup = collector.iteratorGroup;    iteratorGroup.newStackWalk(t);    Address             ip, fp, prevFp;    if (top_frame.isZero()) {      prevFp = Address.zero();      // start scan using fp & ip in threads saved context registers      ip = t.contextRegisters.getInnermostInstructionAddress();      fp = t.contextRegisters.getInnermostFramePointer();    } else {      prevFp = top_frame;      // start scan at caller of passed in fp      ip = VM_Magic.getReturnAddress(top_frame);      fp = VM_Magic.getCallerFramePointer(top_frame);    }    if (DUMP_STACK >= 1) {      VM.sysWriteln("  top_frame = ", top_frame);      VM.sysWriteln("         ip = ", ip);      VM.sysWriteln("         fp = ", fp);      VM.sysWriteln("  registers.ip = ", t.contextRegisters.ip);    }        if (DUMP_STACK >= 2 && t.jniEnv != null)         t.jniEnv.dumpJniRefsStack();    // It is possible to have a stack with only Native C frames, for a thread    // that started in C, "attached" to the VM, made JNIFunction calls, and    // has now returned back to C. In this case, scanStack should be called    // with a "topJavaFrame" = 0. There may be references in the threads    // JNIrefs side stack that need to be processed, below after the loop.    if ( fp.NE(sentinelFP)) {      // At start of loop:      //   fp -> frame for method invocation being processed      //   ip -> instruction pointer in the method (normally a call site)            while (VM_Magic.getCallerFramePointer(fp).NE(sentinelFP)) {                int compiledMethodId = VM_Magic.getCompiledMethodID(fp);                // Reflection and jni generate "invisible" transition frames with        // method_id == 0.  Such frames are skipped here. For PowerPC        // JNI C to java transitions frames exist, but should be skipped at the        // end of this loop during incrementing to the "next" frame.        //        // Everything after this if-block is for normal Java (and JNI Java to C transition) frames        //        if (compiledMethodId == VM_Constants.INVISIBLE_METHOD_ID) {                    if (DUMP_STACK >= 1) VM.sysWrite("\n--- METHOD <invisible method>\n");                    prevFp = fp;          ip = VM_Magic.getReturnAddress(fp);          fp = VM_Magic.getCallerFramePointer(fp);          continue;        }                VM_CompiledMethod compiledMethod = VM_CompiledMethods.getCompiledMethod(compiledMethodId);        compiledMethod.setObsolete(false);  // keeps code object alive        VM_Method method = compiledMethod.getMethod();        int compiledMethodType = compiledMethod.getCompilerType();        if (DUMP_STACK >= 1)           printMethodHeader(compiledMethod, fp, ip);        if (compiledMethodType == VM_CompiledMethod.TRAP) {          ip = VM_Magic.getReturnAddress(fp);          fp = VM_Magic.getCallerFramePointer(fp);          continue;        }        // initialize MapIterator for this frame        VM_CodeArray codeArray = compiledMethod.getInstructions();        Offset offset = ip.diff(VM_Magic.objectAsAddress(codeArray));        if (compiledMethodType != VM_CompiledMethod.JNI) {          Offset possibleLen = Offset.fromIntZeroExtend(codeArray.length() << LG_INSTRUCTION_WIDTH);          if (offset.sLT(Offset.zero()) || possibleLen.sLT(offset)) {            // We have an invalid offset            if (offset.sLT(Offset.zero())) {              VM.sysWriteln("ScanThread: computed instruction offset is negative ", offset);            } else {              VM.sysWriteln("ScanThread: computed instruction offset is too big");              VM.sysWrite("\toffset is", offset);              VM.sysWriteln(" bytes of machine code for method ",possibleLen);            }            VM.sysWrite("\tSupposed method: ");            VM.sysWrite(method);            VM.sysWriteln("\n\tBase of its code array", ObjectReference.fromObject(codeArray));            Address ra = VM_Magic.objectAsAddress(codeArray).add(offset);            VM.sysWriteln("\tCalculated actual return address is ", ra);            VM_CompiledMethod realCM = VM_CompiledMethods.findMethodForInstruction(ra);            if (realCM == null) {              VM.sysWriteln("\tUnable to find compiled method corresponding to this return address");            } else {              VM.sysWrite("\tFound compiled method ");              VM.sysWrite(realCM.getMethod());              VM.sysWriteln(" whose code contains this return address");            }            VM.sysWriteln("Attempting to dump suspect stack and then exit\n");            VM_Scheduler.dumpStackAndDie(top_frame);          }        }        VM_GCMapIterator iterator = iteratorGroup.selectIterator(compiledMethod);        iterator.setupIterator(compiledMethod, offset.toInt(), fp);                if (DUMP_STACK >= 2) dumpStackFrame( fp, prevFp );                if (DUMP_STACK >= 3)          VM.sysWrite("--- Refs Reported By GCMap Iterator ---\n");                // scan the map for this frame and process each reference        //        for (Address refaddr = iterator.getNextReferenceAddress(); !refaddr.isZero();             refaddr = iterator.getNextReferenceAddress()) {                    if (VM.VerifyAssertions && VALIDATE_STACK_REFS) {            ObjectReference ref = refaddr.loadObjectReference();            if (!MM_Interface.validRef(ref)) {              VM.sysWrite("\nInvalid ref reported while scanning stack\n");              printMethodHeader(compiledMethod, fp, ip);              VM.sysWrite(refaddr); VM.sysWrite(":"); MM_Interface.dumpRef(ref);                dumpStackFrame( fp, prevFp );              VM.sysWrite("\nDumping stack starting at frame with bad ref:\n");              VM_Scheduler.dumpStack( ip, fp );              // start stact starting at top              Address top_ip = t.contextRegisters.getInnermostInstructionAddress();              Address top_fp = t.contextRegisters.getInnermostFramePointer();              VM_Scheduler.dumpStack( top_ip, top_fp );              VM.sysFail("\n\nVM_ScanStack: Detected bad GC map; exiting RVM with fatal error");            }          }          if (DUMP_STACK >= 3) {            ObjectReference ref = refaddr.loadObjectReference();            VM.sysWrite(refaddr);             if (DUMP_STACK >= 4) {                VM.sysWrite(":"); MM_Interface.dumpRef(ref);            }            else                VM.sysWriteln();          }                    rootLocations.push(refaddr);      }      if (codeLocations != null) {        // process the code object for the method, and if it is moved, relocate        // the saved ip and any internal code pointers (JSR subroutine return        // addresses. Note, the instructions field of the VM_Method object is        // NOT updated at this time, so that other invocations of the same        // method can use the original address to compute the relocation delta.        //        ObjectReference code = ObjectReference.fromObject(compiledMethod.getInstructions());        if (prevFp.isZero()) {          // top-most stack frame, ip saved in threads context regs          if (DUMP_STACK >= 2) {            VM.sysWriteln(" t.contextRegisters.ip    = ", t.contextRegisters.ip);            VM.sysWriteln("*t.contextRegisters.iploc = ",                           t.contextRegisters.getIPLocation().loadAddress());          }          if (compiledMethodType != VM_CompiledMethod.JNI) {            codeLocationsPush(codeLocations, code, t.contextRegisters.getIPLocation(), 2, t);          } else {            if (DUMP_STACK >= 3)              VM.sysWriteln("GC Warning: SKIPPING return address for JNI code");          }        } else {          Address returnAddressLoc = VM_Magic.getReturnAddressLocation(prevFp);          Address returnAddress = returnAddressLoc.loadAddress();          if (DUMP_STACK >= 3)            VM.sysWriteln("--- Processing return address ", returnAddress,                          " located at ", returnAddressLoc);          if (!DebugUtil.addrInBootImage(returnAddress))            codeLocationsPush(codeLocations, code, returnAddressLoc, 3, t);        }                // scan for internal code pointers in the stack frame and relocate        iterator.reset();        for (Address retaddrLoc = iterator.getNextReturnAddressAddress();  !retaddrLoc.isZero();             retaddrLoc = iterator.getNextReturnAddressAddress()) {          codeLocationsPush(codeLocations, code, retaddrLoc, 4, t);        }      }            iterator.cleanupPointers();            // if at a JNIFunction method, it is preceeded by native frames that must be skipped      //      if (compiledMethod.getMethod().getDeclaringClass().isBridgeFromNative()) {        // skip native frames, stopping at last native frame PRECEEDING the        // Java To C transition frame        fp = VM_Runtime.unwindNativeStackFrameForGC(fp);                if (DUMP_STACK >= 1) VM.sysWrite("scanStack skipping native C frames\n");      }                   // set fp & ip for next frame      prevFp = fp;      ip = VM_Magic.getReturnAddress(fp);      fp = VM_Magic.getCallerFramePointer(fp);            } // end of while != sentinel          } // end of if (fp != STACKFRAME_SENTINEL_FP)        // if we are scanning the stack of a thread that entered the VM    // via a createVM or attachVM then the "bottom" of the stack had    // native C frames instead of the usual java frames.  The JNIEnv    // for the thread may still contain jniRefs that have been    // returned to the native C code, but have not been reported for    // GC.  calling getNextReferenceAddress without first calling    // setup... will report the remaining jniRefs in the current    // "frame" of the jniRefs stack.  (this should be the bottom    // frame)    //    //-#if RVM_FOR_AIX    VM_GCMapIterator iterator = iteratorGroup.getJniIterator();    Address refaddr =  iterator.getNextReferenceAddress();    while( !refaddr.isZero() ) {      rootLocations.push(refaddr);      refaddr =  iterator.getNextReferenceAddress();    }    //-#else    // exclude PPC FOR LINUX    //-#endif        if (DUMP_STACK >= 1) VM.sysWrite("--- End Of Stack Scan ---\n");      } // scanStack