/*
* 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.ia32;
import static org.jikesrvm.compilers.baseline.AbstractBaselineGCMapIterator.TRACE_ALL;
import static org.jikesrvm.compilers.baseline.AbstractBaselineGCMapIterator.TRACE_DL;
import static org.jikesrvm.ia32.BaselineConstants.LG_WORDSIZE;
import static org.jikesrvm.ia32.BaselineConstants.WORDSIZE;
import static org.jikesrvm.ia32.RegisterConstants.NUM_PARAMETER_GPRS;
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.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 IA32 compilers.
* This includes processing of parameters spilled by the IA32 opt compiler.
*/
@Uninterruptible
class ArchBridgeDataExtractor extends AbstractBridgeDataExtractor {
/** gpr register it lives in */
private int bridgeRegisterIndex;
/** do we need to map spilled params (baseline compiler = no, opt = yes) */
private boolean bridgeSpilledParameterMappingRequired;
/** starting offset to stack location for param0 */
private int bridgeSpilledParamInitialOffset;
@Override
protected final void setupBridgeRegisterIndex() {
bridgeRegisterIndex = 0;
}
@Override
public final void resetBridgeRegisterIndex() {
bridgeRegisterIndex = 0;
}
@Override
protected final void setupArchitectureSpecificDynamicBridgeMapping(Address fp) {
Address ip = Magic.getReturnAddressUnchecked(fp);
fp = Magic.getCallerFramePointer(fp);
int callingCompiledMethodId = Magic.getCompiledMethodID(fp);
CompiledMethod callingCompiledMethod = CompiledMethods.getCompiledMethod(callingCompiledMethodId);
Offset callingInstructionOffset = callingCompiledMethod.getInstructionOffset(ip);
updateWithInfoForDynamicLink(callingCompiledMethod, callingInstructionOffset);
if (dynamicLink.isInvokedWithImplicitThisParameter()) {
bridgeSpilledParamInitialOffset = 2 * WORDSIZE; // this + return addr
} else {
bridgeSpilledParamInitialOffset = WORDSIZE; // return addr
}
bridgeSpilledParamInitialOffset += (bridgeTarget.getParameterWords() << LG_WORDSIZE);
bridgeSpilledParameterMappingRequired = callingCompiledMethod.getCompilerType() != CompiledMethod.BASELINE;
}
@Override
public final void resetBridgeSpilledParamLocation(Address framePtr) {
bridgeSpilledParamLocation = framePtr.plus(bridgeSpilledParamInitialOffset);
}
@Override
public final void incBridgeRegisterIndex() {
bridgeRegisterIndex++;
}
@Override
public final boolean unprocessedBridgeRegistersRemain() {
return bridgeRegisterIndex <= NUM_PARAMETER_GPRS;
}
public final boolean isBridgeSpilledParameterMappingRequired() {
return bridgeSpilledParameterMappingRequired;
}
@Override
public final Address getImplicitThisAddress() {
bridgeParameterIndex++;
incBridgeRegisterIndex();
decBrigeRegisterLocation(WORDSIZE);
bridgeSpilledParamLocation = bridgeSpilledParamLocation.minus(WORDSIZE);
if (VM.TraceStkMaps || TRACE_ALL || TRACE_DL) {
VM.sysWrite("BaselineGCMapIterator getNextReferenceOffset = dynamic link GPR this ");
VM.sysWrite(bridgeRegisterLocation.plus(WORDSIZE));
VM.sysWriteln(".");
}
return bridgeRegisterLocation.plus(WORDSIZE);
}
@Override
public final Address getNextBridgeParameterAddress() {
if (!hasMoreBridgeParameters()) {
return Address.zero();
}
TypeReference bridgeParameterType = bridgeParameterTypes[bridgeParameterIndex++];
boolean paramIsRef = bridgeParameterType.isReferenceType();
// Skip over non-reference parameters
while (!paramIsRef) {
if (bridgeParameterType.isLongType()) {
if (VM.BuildFor32Addr) {
incBridgeRegisterIndex();
incBridgeRegisterIndex();
decBrigeRegisterLocation(2 * WORDSIZE);
} else {
incBridgeRegisterIndex();
decBrigeRegisterLocation(WORDSIZE);
}
bridgeSpilledParamLocation = bridgeSpilledParamLocation.minus(2 * WORDSIZE);
} else if (bridgeParameterType.isDoubleType()) {
bridgeSpilledParamLocation = bridgeSpilledParamLocation.minus(2 * WORDSIZE);
} else if (bridgeParameterType.isFloatType()) {
bridgeSpilledParamLocation = bridgeSpilledParamLocation.minus(WORDSIZE);
} else {
// boolean, byte, char, short, int
incBridgeRegisterIndex();
decBrigeRegisterLocation(WORDSIZE);
bridgeSpilledParamLocation = bridgeSpilledParamLocation.minus(WORDSIZE);
}
if (hasMoreBridgeParameters()) {
bridgeParameterType = bridgeParameterTypes[bridgeParameterIndex++];
paramIsRef = bridgeParameterType.isReferenceType();
} else {
return Address.zero();
}
}
if (VM.VerifyAssertions) VM._assert(bridgeParameterType.isReferenceType());
incBridgeRegisterIndex();
decBrigeRegisterLocation(WORDSIZE);
bridgeSpilledParamLocation = bridgeSpilledParamLocation.minus(WORDSIZE);
if (unprocessedBridgeRegistersRemain()) {
if (VM.TraceStkMaps || TRACE_ALL || TRACE_DL) {
VM.sysWrite("BaselineGCMapIterator getNextReferenceOffset = dynamic link GPR parameter ");
VM.sysWrite(bridgeRegisterLocation.plus(WORDSIZE));
VM.sysWriteln(".");
}
return bridgeRegisterLocation.plus(WORDSIZE);
} else {
if (isBridgeSpilledParameterMappingRequired()) {
if (VM.TraceStkMaps || TRACE_ALL || TRACE_DL) {
VM.sysWrite("BaselineGCMapIterator getNextReferenceOffset = dynamic link spilled parameter ");
VM.sysWrite(bridgeSpilledParamLocation.plus(WORDSIZE));
VM.sysWriteln(".");
}
return bridgeSpilledParamLocation.plus(WORDSIZE);
} else {
// fallthrough to return
}
}
return Address.zero();
}
public final void traceBridgeTarget() {
VM.sysWrite("getNextReferenceAddress: bridgeTarget=");
VM.sysWrite(bridgeTarget);
VM.sysWriteln();
}
}