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 */
013package org.jikesrvm.compilers.opt.runtimesupport;
014
015import org.jikesrvm.VM;
016import org.jikesrvm.compilers.common.CompiledMethods;
017import org.jikesrvm.runtime.Magic;
018import org.jikesrvm.scheduler.RVMThread;
019import org.vmmagic.pragma.Entrypoint;
020import org.vmmagic.pragma.Interruptible;
021import org.vmmagic.pragma.SaveVolatile;
022import org.vmmagic.pragma.Unpreemptible;
023import org.vmmagic.unboxed.Address;
024import org.vmmagic.unboxed.Offset;
025
026/**
027 * Contains routines that must be compiled with special prologues and eplilogues that
028 * save/restore all registers (both volatile and non-volatile).<p>
029 *
030 * TODO: Instead of SaveVolatile, make this class implement
031 * DynamicBridge...will allow us to kill support for SaveVolatile!.<p>
032 *
033 * ISSUE: GCMapping for dynamic bridge assumes that it is being used for
034 *        lazy method compilation.  Need to generalize to support
035 *        opt's use for other purposes.
036 *
037 * @see org.jikesrvm.compilers.opt.driver.OptimizingCompiler (hooks to recognize &amp; specially compile this class)
038 */
039@SaveVolatile
040@Unpreemptible("Yield methods shouldn't be preempted")
041public class OptSaveVolatile {
042
043  /**
044   * Handle timer interrupt taken in method prologue.
045   * This method is identical to the yieldpointFromPrologue()
046   * method used by the baseline compiler, except in the OPT compiler world,
047   * we also save the volatile registers.
048   */
049  @Entrypoint
050  public static void yieldpointFromPrologue() {
051    Address fp = Magic.getFramePointer();
052    RVMThread.yieldpoint(RVMThread.PROLOGUE, fp);
053  }
054
055  /**
056   * Handle timer interrupt taken in method epilogue.
057   * This method is identical to the yieldpointFromEpilogue()
058   * method used by the baseline compiler, except in the OPT compiler world,
059   * we also save the volatile registers.
060   */
061  @Entrypoint
062  public static void yieldpointFromEpilogue() {
063    Address fp = Magic.getFramePointer();
064    RVMThread.yieldpoint(RVMThread.EPILOGUE, fp);
065  }
066
067  /**
068   * Handle timer interrupt taken on loop backedge.
069   * This method is identical to the yieldpointFromBackedge() method used
070   * method used by the baseline compiler, except in the OPT compiler world,
071   * we also save the volatile registers.
072   */
073  @Entrypoint
074  public static void yieldpointFromBackedge() {
075    Address fp = Magic.getFramePointer();
076    RVMThread.yieldpoint(RVMThread.BACKEDGE, fp);
077  }
078
079  /**
080   * Handle timer interrupt taken in the prologue of a native method.
081   */
082  @Entrypoint
083  public static void yieldpointFromNativePrologue() {
084    // VM.sysWriteln(123);
085    // VM.sysWriteln(Magic.getFramePointer());
086    // VM.sysWriteln(Magic.getCallerFramePointer(Magic.getFramePointer()));
087    // System.gc();
088    // VM.sysWriteln("Survived GC");
089    // Address fp = Magic.getFramePointer();
090    // Thread.yieldpoint(Thread.NATIVE_PROLOGUE, fp);
091  }
092
093  /**
094   * Handle timer interrupt taken in the epilogue of a native method.
095   */
096  @Entrypoint
097  public static void yieldpointFromNativeEpilogue() {
098    // VM.sysWriteln(321);
099    // VM.sysWriteln(Magic.getFramePointer());
100    // VM.sysWriteln(Magic.getCallerFramePointer(Magic.getFramePointer()));
101    // System.gc();
102    // VM.sysWriteln("Survived GC");
103    // Address fp = Magic.getFramePointer();
104    // Thread.yieldpoint(Thread.NATIVE_EPILOGUE, fp);
105  }
106
107  /**
108   * OSR invalidation being initiated.
109   */
110  @Entrypoint
111  public static void yieldpointFromOsrOpt() {
112    Address fp = Magic.getFramePointer();
113    RVMThread.getCurrentThread().yieldToOSRRequested = true;
114    RVMThread.getCurrentThread().takeYieldpoint = 1;
115    RVMThread.yieldpoint(RVMThread.OSROPT, fp);
116  }
117
118  /**
119   * Wrapper to save/restore volatile registers when a class needs to be
120   * dynamically loaded/resolved/etc.
121   */
122  @Interruptible
123  public static void resolve() throws NoClassDefFoundError {
124    VM.disableGC();
125    // (1) Get the compiled method & compilerInfo for the (opt)
126    // compiled method that called resolve
127    Address fp = Magic.getCallerFramePointer(Magic.getFramePointer());
128    int cmid = Magic.getCompiledMethodID(fp);
129    OptCompiledMethod cm = (OptCompiledMethod) CompiledMethods.getCompiledMethod(cmid);
130    // (2) Get the return address
131    Address ip = Magic.getReturnAddressUnchecked(Magic.getFramePointer());
132    Offset offset = cm.getInstructionOffset(ip);
133    VM.enableGC();
134    // (3) Call the routine in OptLinker that does all the real work.
135    OptLinker.resolveDynamicLink(cm, offset);
136  }
137}