lastFrame -= 1;
for ( ; lastFrame > 0 ; --lastFrame) { VM_Method m = compiledMethods[lastFrame].getMethod(); if (m == VM_Entrypoints.threadStartoffMethod) continue;              if (m == VM_Entrypoints.threadRunMethod) continue;              if (m == VM_Entrypoints.mainThreadRunMethod) continue;               break; }
  private void print4Real(PrintLN out, Throwable trigger, int depth) {    //    out.println("Calling print(out, trigger = " + trigger.toString() + ")"); // DEBUG XXX    if (depth > printingMaxDepth) {      VM.sysWriteln("VM_StackTrace.print4Real(): Already ", depth, " levels deep in a recursive stack trace; won't show trace # ", traceIndex);      return;                   // feign success    }    /** Where'd we find the trigger? */    int foundTriggerAt = -1;    // -1 is a sentinel value; important in code                                // below.     int lastFrame = compiledMethods.length - 1;    // The last two stack frames are always:    // --> at com.ibm.JikesRVM.MainThread.run (MainThread.java:117)    // --> at com.ibm.JikesRVM.VM_Thread.startoff (VM_Thread.java:710)    // so we can skip them, right?  If this was not the right thing to do,    // please tell me. --Steve Augart    // True for main thread, but if the program spawns other threads than    // this isn't the case. We can always cut the VM_Thread.startoff frame    // every thread (I think), but for threads other than the main thread,     // the second frame is actually interesting. --dave    lastFrame -= 1;        if (trigger != null) {      Class triggerClass = trigger.getClass();      /* So, elide up to the triggeringMethod.  If we never find the         triggeringMethod, then leave foundTriggerAt set to -1; the printing         code will handle that correctly.. */      for (int i = 0; i <= lastFrame; ++i) {        VM_CompiledMethod cm = compiledMethods[i];        if (cm == null || cm.getCompilerType() == VM_CompiledMethod.TRAP)          continue;        VM_Method m = cm.getMethod();        /* Declaring class of the method whose call is recorded in this stack         * frame.  */         VM_Class frameVM_Class = m.getDeclaringClass();        if (frameVM_Class.getClassForType() == triggerClass) {          foundTriggerAt = i;          break;        }      }    }    /* foundTriggerAt should either be between 0 and lastFrame       or it should be -1. */    // Handle case where an out of line machine code frame is    // at compiledMethods[foundTriggerAt +1].    // Happens when the exception object being thrown is created via    // reflection (which is how JNI does it).     while (foundTriggerAt+2 < compiledMethods.length &&           compiledMethods[foundTriggerAt +1] == null) {      foundTriggerAt++;    }    /* Now check to see if the triggering frame is VM_Runtime.deliverHardwareException.       If it is, then skip two more frames to avoid showing it and the       <hardware trap> frame that called it */    VM_CompiledMethod bottom = compiledMethods[foundTriggerAt +1];    if (bottom.getMethod() == VM_Entrypoints.deliverHardwareExceptionMethod) {      foundTriggerAt += 2;    }    /* Now we can start printing frames. */    int nPrinted = 0;           // how many frames have we printed?    for (int i = foundTriggerAt + 1; i <= lastFrame; ++i, ++nPrinted) {      VM_CompiledMethod cm = compiledMethods[i];      if (nPrinted == elideAfterThisManyFrames) {        // large stack - suppress excessive output        int oldIndex = i;        int newIndex = lastFrame - 9;        if (newIndex > oldIndex) {          i = newIndex;          try {            out.print("\t...");            out.print(newIndex - oldIndex);            out.println(" stackframes omitted.");            // out.println("\t..." + (newIndex - oldIndex) + " stackframes omitted...");          } catch (OutOfMemoryError e) {            trigger.tallyOutOfMemoryError();            if (out.isSysWrite()) {              VM.sysWriteln("\t... <some stack frames elided (also, Out of memory)>");            } else {              VM.sysWriteln("VM_StackTrace.print4Real(): Caught OutOfMemoryError while trying to display how many stack frames are omitted (elided).");              VM.sysWriteln("VM_StackTrace.print4Real(): Relaunching the error");                            throw e;          // launch again, for our caller.            }          }        }      }      try {        if (cm == null) {          out.println("\tat <invisible method>");          /* Commented out; Work in Progress: *///      } else if (cm.getMethod() == runMethodMarkingPrelude) {//      /* cm.getMethod() yields a VM_Method. *///      /* Notice that if runMethodMarkingPrelude is null, the right thing//         happens here. *///              return;                 // gone far enough.        } else {          cm.printStackTrace(offsets[i], out);        }      }      catch (OutOfMemoryError e) {        trigger.tallyOutOfMemoryError();        if (out.isSysWrite()) {          VM.sysWriteln("\tat <one undisplayable stack frame (Out of Memory) >");        } else {          try {            out.flush();            // The output's been flushed, I guess.  Make sure the line ends            // cleanly.             VM.sysWriteln();          } catch (OutOfMemoryError e2) {            trigger.tallyOutOfMemoryError();            VM.sysWriteln();            VM.sysWriteln("VM_StackTrace.print4Real(): Caught OutOfMemoryError while flushing output.   Going on.");          }          VM.sysWriteln("VM_StackTrace.print4Real(): Caught OutOfMemoryError while printing one frame of stack trace.  Re-throw()ing it.");          throw e;              // pass up to caller.        }      }    }  }