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 & 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}