/** * Wrapper to save/restore volatile registers when a class needs to be dynamically * loaded/resolved/etc. */ @Interruptible public static void OPT_resolve() throws NoClassDefFoundError { VM.disableGC(); // (1) Get the compiled method & compilerInfo for the (opt) // compiled method that called OPT_resolve LocalAddress fp = VM_Magic.getCallerFramePointer(VM_Magic.getFramePointer()); int cmid = VM_Magic.getCompiledMethodID(fp); VM_OptCompiledMethod cm = (VM_OptCompiledMethod) VM_CompiledMethods.getCompiledMethod(cmid); // (2) Get the return address LocalAddress ip = VM_Magic.getReturnAddress(VM_Magic.getFramePointer()); Offset offset = cm.getInstructionOffset(ip); VM.enableGC(); // (3) Call the routine in VM_OptLinker that does all the real work. VM_OptLinker.resolveDynamicLink(cm, offset); }
// Create a conflict resolution stub for the set of interface method signatures l. // public static ArchitectureSpecific.VM_CodeArray createStub(int[] sigIds, VM_Method[] targets) { // (1) Create an assembler. int numEntries = sigIds.length; VM_Assembler asm = new ArchitectureSpecific.VM_Assembler(numEntries); // pretend each entry is a bytecode // (2) signatures must be in ascending order (to build binary search tree). if (VM.VerifyAssertions) { for (int i = 1; i < sigIds.length; i++) { VM._assert(sigIds[i - 1] < sigIds[i]); } } // (3) Assign synthetic bytecode numbers to each switch such that we'll generate them // in ascending order. This lets us use the general forward branching mechanisms // of the VM_Assembler. int[] bcIndices = new int[numEntries]; assignBytecodeIndices(0, bcIndices, 0, numEntries - 1); // (4) Generate the stub. insertStubPrologue(asm); insertStubCase(asm, sigIds, targets, bcIndices, 0, numEntries - 1); ArchitectureSpecific.VM_CodeArray stub = asm.makeMachineCode().getInstructions(); // (5) synchronize icache with generated machine code that was written through dcache if (VM.runningVM) VM_Memory.sync(VM_Magic.objectAsAddress(stub), stub.length() << LG_INSTRUCTION_WIDTH); return stub; }
/** OSR invalidation being initiated. */ @Entrypoint public static void OPT_yieldpointFromOsrOpt() { LocalAddress fp = VM_Magic.getFramePointer(); VM_Processor.getCurrentProcessor().yieldToOSRRequested = true; VM_GreenThread.yieldpoint(VM_Thread.OSROPT, fp); }
/** * Handle timer interrupt taken on loop backedge. This method is identical to the * yieldpointFromBackedge() method used method used by the baseline compiler, except in the OPT * compiler world, we also save the volatile registers. */ @Entrypoint public static void OPT_yieldpointFromBackedge() { LocalAddress fp = VM_Magic.getFramePointer(); VM_GreenThread.yieldpoint(VM_Thread.BACKEDGE, fp); }
/** * Handle timer interrupt taken in method epilogue. This method is identical to the * yieldpointFromEpilogue() method used by the baseline compiler, except in the OPT compiler * world, we also save the volatile registers. */ @Entrypoint public static void OPT_yieldpointFromEpilogue() { LocalAddress fp = VM_Magic.getFramePointer(); VM_GreenThread.yieldpoint(VM_Thread.EPILOGUE, fp); }