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).<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 & specially compile this class)
038     */
039    @SaveVolatile
040    @Unpreemptible("Yield methods shouldn't be preempted")
041    public 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    }