/* * This file is part of the Jikes RVM project (http://jikesrvm.org). * * This file is licensed to You under the Eclipse Public License (EPL); * 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/eclipse-1.0.php * * See the COPYRIGHT.txt file distributed with this work for information * regarding copyright ownership. */ package org.jikesrvm.compilers.baseline.ppc; import static org.jikesrvm.compilers.baseline.AbstractBaselineGCMapIterator.TRACE_ALL; import static org.jikesrvm.compilers.baseline.AbstractBaselineGCMapIterator.TRACE_DL; import static org.jikesrvm.ppc.RegisterConstants.FIRST_VOLATILE_GPR; import static org.jikesrvm.ppc.RegisterConstants.LAST_VOLATILE_GPR; import static org.jikesrvm.ppc.StackframeLayoutConstants.STACKFRAME_HEADER_SIZE; import static org.jikesrvm.runtime.JavaSizeConstants.BYTES_IN_DOUBLE; import static org.jikesrvm.runtime.JavaSizeConstants.BYTES_IN_FLOAT; import static org.jikesrvm.runtime.JavaSizeConstants.BYTES_IN_LONG; import static org.jikesrvm.runtime.UnboxedSizeConstants.BYTES_IN_ADDRESS; import org.jikesrvm.VM; import org.jikesrvm.classloader.TypeReference; import org.jikesrvm.compilers.baseline.AbstractBridgeDataExtractor; import org.jikesrvm.compilers.common.CompiledMethod; import org.jikesrvm.compilers.common.CompiledMethods; import org.jikesrvm.ppc.RegisterConstants.GPR; import org.jikesrvm.runtime.Magic; import org.vmmagic.pragma.Uninterruptible; import org.vmmagic.unboxed.Address; import org.vmmagic.unboxed.Offset; /** * This class implements the extracting of bridge data for the PowerPC compilers. * This includes processing of the register spill areas. */ @Uninterruptible final class ArchBridgeDataExtractor extends AbstractBridgeDataExtractor { /** gpr register it lives in */ private GPR bridgeRegisterIndex; @Override protected void setupBridgeRegisterIndex() { bridgeRegisterIndex = GPR.R0; } @Override public void resetBridgeRegisterIndex() { bridgeRegisterIndex = FIRST_VOLATILE_GPR; } @Override protected void setupArchitectureSpecificDynamicBridgeMapping(Address fp) { fp = Magic.getCallerFramePointer(fp); Address ip = Magic.getNextInstructionAddress(fp); int callingCompiledMethodId = Magic.getCompiledMethodID(fp); CompiledMethod callingCompiledMethod = CompiledMethods.getCompiledMethod(callingCompiledMethodId); Offset callingInstructionOffset = callingCompiledMethod.getInstructionOffset(ip); updateWithInfoForDynamicLink(callingCompiledMethod, callingInstructionOffset); } @Override public void resetBridgeSpilledParamLocation(Address callersFp) { bridgeSpilledParamLocation = callersFp.plus(STACKFRAME_HEADER_SIZE); } @Override public void incBridgeRegisterIndex() { bridgeRegisterIndex = bridgeRegisterIndex.nextGPR(); } @Override public boolean unprocessedBridgeRegistersRemain() { return bridgeRegisterIndex.value() <= LAST_VOLATILE_GPR.value(); } @Override public Address getImplicitThisAddress() { bridgeParameterIndex++; incBridgeRegisterIndex(); incBrigeRegisterLocation(BYTES_IN_ADDRESS); if (VM.TraceStkMaps || TRACE_ALL || TRACE_DL) { VM.sysWrite("BaselineGCMapIterator getNextReferenceOffset, "); VM.sysWrite(" this, bridge, returning: "); VM.sysWrite(bridgeRegisterLocation.minus(BYTES_IN_ADDRESS)); VM.sysWriteln(); } return bridgeRegisterLocation.minus(BYTES_IN_ADDRESS); } @Override public Address getNextBridgeParameterAddress() { while (hasMoreBridgeParameters()) { TypeReference bridgeParameterType = bridgeParameterTypes[bridgeParameterIndex++]; // are we still processing the regs? if (unprocessedBridgeRegistersRemain()) { // update the bridgeRegisterLocation (based on type) and return a value if it is a ref if (bridgeParameterType.isReferenceType()) { incBrigeRegisterLocation(BYTES_IN_ADDRESS); incBridgeRegisterIndex(); if (VM.TraceStkMaps || TRACE_ALL || TRACE_DL) { VM.sysWrite("BaselineGCMapIterator getNextReferenceOffset, "); VM.sysWrite(" parm: "); VM.sysWrite(bridgeRegisterLocation.minus(BYTES_IN_ADDRESS)); VM.sysWriteln(); } return bridgeRegisterLocation.minus(BYTES_IN_ADDRESS); } else if (bridgeParameterType.isLongType()) { incBridgeRegisterIndex(); if (VM.BuildFor32Addr) incBridgeRegisterIndex(); incBrigeRegisterLocation(BYTES_IN_LONG); } else if (bridgeParameterType.isFloatingPointType()) { // nothing to do, these are not stored in gprs } else { // boolean, byte, char, short, int incBridgeRegisterIndex(); incBrigeRegisterLocation(BYTES_IN_ADDRESS); } } else { // now process the register spill area for the remain params // no need to update BridgeRegisterIndex anymore, it isn't used and is already // big enough (> LAST_VOLATILE_GPR) to ensure we'll live in this else code in the future if (bridgeParameterType.isReferenceType()) { bridgeSpilledParamLocation = bridgeSpilledParamLocation.plus(BYTES_IN_ADDRESS); if (VM.TraceStkMaps || TRACE_ALL || TRACE_DL) { VM.sysWrite("BaselineGCMapIterator getNextReferenceOffset, dynamic link spilled parameter, returning: "); VM.sysWrite(bridgeSpilledParamLocation.minus(BYTES_IN_ADDRESS)); VM.sysWriteln("."); } return bridgeSpilledParamLocation.minus(BYTES_IN_ADDRESS); } else if (bridgeParameterType.isLongType()) { bridgeSpilledParamLocation = bridgeSpilledParamLocation.plus(BYTES_IN_LONG); } else if (bridgeParameterType.isDoubleType()) { bridgeSpilledParamLocation = bridgeSpilledParamLocation.plus(BYTES_IN_DOUBLE); } else if (bridgeParameterType.isFloatType()) { bridgeSpilledParamLocation = bridgeSpilledParamLocation.plus(BYTES_IN_FLOAT); } else { // boolean, byte, char, short, int bridgeSpilledParamLocation = bridgeSpilledParamLocation.plus(BYTES_IN_ADDRESS); } } } return Address.zero(); } }