001    /*
002     *  This file is part of the Jikes RVM project (http://jikesrvm.org).
003     *
004     *  This file is licensed to You under the Eclipse Public License (EPL);
005     *  You may not use this file except in compliance with the License. You
006     *  may obtain a copy of the License at
007     *
008     *      http://www.opensource.org/licenses/eclipse-1.0.php
009     *
010     *  See the COPYRIGHT.txt file distributed with this work for information
011     *  regarding copyright ownership.
012     */
013    package org.jikesrvm.osr;
014    
015    import org.jikesrvm.ArchitectureSpecific;
016    import org.jikesrvm.VM;
017    import org.jikesrvm.Constants;
018    import org.jikesrvm.PrintContainer;
019    import org.jikesrvm.compilers.common.CompiledMethod;
020    import org.jikesrvm.compilers.common.CompiledMethods;
021    import org.jikesrvm.runtime.Magic;
022    import org.jikesrvm.runtime.RuntimeEntrypoints;
023    import org.jikesrvm.scheduler.RVMThread;
024    import org.vmmagic.unboxed.Address;
025    import org.vmmagic.unboxed.Offset;
026    
027    /**
028     * A ExecutionStateExtractor extracts a runtime state (VM scope descriptor)
029     * of a method activation. The implementation depends on compilers and
030     * hardware architectures
031     * @see org.jikesrvm.ArchitectureSpecificOpt.BaselineExecutionStateExtractor
032     * @see org.jikesrvm.ArchitectureSpecificOpt.OptExecutionStateExtractor
033     *
034     * It returns a compiler and architecture neutered runtime state
035     * ExecutionState.
036     */
037    
038    public abstract class ExecutionStateExtractor implements Constants {
039      /**
040       * Returns a VM scope descriptor (ExecutionState) for a compiled method
041       * on the top of a thread stack, (or a list of descriptors for an inlined
042       * method).
043       *
044       * @param thread a suspended RVM thread
045       * @param tsFromFPoff the frame pointer offset of the threadSwitchFrom method
046       * @param ypTakenFPoff the frame pointer offset of the real method where
047       *                      yield point was taken. tsFrom is the callee of ypTaken
048       * @param cmid the compiled method id of ypTaken
049       */
050      public abstract ExecutionState extractState(RVMThread thread, Offset tsFromFPoff, Offset ypTakenFPoff, int cmid);
051    
052      public static void printStackTraces(int[] stack, Offset osrFPoff) {
053    
054        VM.disableGC();
055    
056        Address fp = Magic.objectAsAddress(stack).plus(osrFPoff);
057        Address ip = Magic.getReturnAddressUnchecked(fp);
058        fp = Magic.getCallerFramePointer(fp);
059        while (Magic.getCallerFramePointer(fp).NE(ArchitectureSpecific.StackframeLayoutConstants.STACKFRAME_SENTINEL_FP)) {
060          int cmid = Magic.getCompiledMethodID(fp);
061    
062          if (cmid == ArchitectureSpecific.StackframeLayoutConstants.INVISIBLE_METHOD_ID) {
063            VM.sysWriteln(" invisible method ");
064          } else {
065            CompiledMethod cm = CompiledMethods.getCompiledMethod(cmid);
066            Offset instrOff = cm.getInstructionOffset(ip);
067            cm.printStackTrace(instrOff, PrintContainer.get(System.out));
068    
069            if (cm.getMethod().getDeclaringClass().hasBridgeFromNativeAnnotation()) {
070              fp = RuntimeEntrypoints.unwindNativeStackFrame(fp);
071            }
072          }
073    
074          ip = Magic.getReturnAddressUnchecked(fp);
075          fp = Magic.getCallerFramePointer(fp);
076        }
077    
078        VM.enableGC();
079      }
080    }