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