/* * This file is part of the Jikes RVM project (http://jikesrvm.org). * * This file is licensed to You under the Common Public License (CPL); * You may not use this file except in compliance with the License. You * may obtain a copy of the License at * * http://www.opensource.org/licenses/cpl1.0.php * * See the COPYRIGHT.txt file distributed with this work for information * regarding copyright ownership. */ package org.jikesrvm.osr.ppc; import org.jikesrvm.ArchitectureSpecific; import org.jikesrvm.VM; import org.jikesrvm.adaptive.util.VM_AOSLogging; import org.jikesrvm.compilers.baseline.VM_BaselineCompiledMethod; import org.jikesrvm.compilers.baseline.ppc.VM_Compiler; import org.jikesrvm.compilers.common.VM_CompiledMethod; import org.jikesrvm.compilers.common.VM_CompiledMethods; import org.jikesrvm.compilers.common.assembler.ppc.VM_Assembler; import org.jikesrvm.compilers.opt.VM_OptCompiledMethod; import org.jikesrvm.osr.OSR_ExecutionState; import org.jikesrvm.ppc.VM_BaselineConstants; import org.jikesrvm.ppc.VM_MachineCode; import org.jikesrvm.runtime.VM_Magic; import org.jikesrvm.runtime.VM_Memory; import org.jikesrvm.runtime.VM_Statics; import org.jikesrvm.scheduler.VM_Thread; import org.vmmagic.unboxed.Address; import org.vmmagic.unboxed.Offset; /** * OSR_CodeInstaller adjusts registers and return address to make a * specialized thread as a normal thread get scheduled. The method * prologue ( machine code ) is adjusted to cooperate with the code * installer. */ public abstract class OSR_CodeInstaller implements VM_BaselineConstants { /* install the newly compiled instructions. */ public static boolean install(OSR_ExecutionState state, VM_CompiledMethod cm) { VM_Thread thread = state.getThread(); byte[] stack = thread.getStack(); Offset fooFPOffset = state.getFPOffset(); // we are going to dynamically generate some code recover // register values from the stack frame. int foomid = VM_Magic.getIntAtOffset(stack, fooFPOffset.plus(STACKFRAME_METHOD_ID_OFFSET)); VM_CompiledMethod foo = VM_CompiledMethods.getCompiledMethod(foomid); int cType = foo.getCompilerType(); VM_Assembler asm = new ArchitectureSpecific.VM_Assembler(0, VM.TraceOnStackReplacement); ///////////////////////////////////// ////// recover saved registers. ///////////////////////////////////// if (cType == VM_CompiledMethod.BASELINE) { VM_BaselineCompiledMethod bcm = (VM_BaselineCompiledMethod) foo; int offset = VM_Compiler.getFrameSize(bcm); for (int i = bcm.getLastFloatStackRegister(); i >= FIRST_FLOAT_LOCAL_REGISTER; --i) { offset -= BYTES_IN_DOUBLE; asm.emitLFD(i, offset, FP); } for (int i = bcm.getLastFixedStackRegister(); i >= FIRST_FIXED_LOCAL_REGISTER; --i) { offset -= BYTES_IN_ADDRESS; asm.emitLAddr(i, offset, FP); } } else if (cType == VM_CompiledMethod.OPT) { VM_OptCompiledMethod fooOpt = (VM_OptCompiledMethod) foo; // foo definitely not save volatile. boolean saveVolatile = fooOpt.isSaveVolatile(); if (VM.VerifyAssertions) { VM._assert(!saveVolatile); } int offset = fooOpt.getUnsignedNonVolatileOffset(); // recover nonvolatile GPRs int firstGPR = fooOpt.getFirstNonVolatileGPR(); if (firstGPR != -1) { for (int i = firstGPR; i <= LAST_NONVOLATILE_GPR; i++) { asm.emitLAddr(i, offset, FP); offset += BYTES_IN_STACKSLOT; } } // recover nonvolatile FPRs int firstFPR = fooOpt.getFirstNonVolatileFPR(); if (firstFPR != -1) { for (int i = firstFPR; i <= LAST_NONVOLATILE_FPR; i++) { asm.emitLFD(i, offset, FP); offset += BYTES_IN_DOUBLE; } } } if (VM.VerifyAssertions) { Object jtocContent = VM_Statics.getSlotContentsAsObject(cm.getOsrJTOCoffset()); VM._assert(jtocContent == cm.getEntryCodeArray()); } // load address of newInstructions from JTOC asm.emitLAddrToc(S0, cm.getOsrJTOCoffset()); // mov CTR addr asm.emitMTCTR(S0); // lwz FP, 0(FP) asm.emitLAddr(FP, 0, FP); // lwz T0, NEXT_INSTR(FP) asm.emitLAddr(S0, STACKFRAME_NEXT_INSTRUCTION_OFFSET, FP); // mov LR, addr asm.emitMTLR(S0); // bctr asm.emitBCCTR(); VM_MachineCode mc = asm.makeMachineCode(); // mark the thread as waiting for on stack replacement. thread.isWaitingForOsr = true; thread.bridgeInstructions = mc.getInstructions(); thread.fooFPOffset = fooFPOffset; Address bridgeaddr = VM_Magic.objectAsAddress(thread.bridgeInstructions); VM_Memory.sync(bridgeaddr, thread.bridgeInstructions.length() << LG_INSTRUCTION_WIDTH); VM_AOSLogging.logOsrEvent("OSR code installation succeeded"); return true; } }