/rvm/src/org/jikesrvm/compilers/baseline/ppc/BaselineGCMapIterator.java
Java | 269 lines | 177 code | 33 blank | 59 comment | 41 complexity | 38c649c76f538b0609fa120ea2d2b753 MD5 | raw file
- /*
- * 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.ppc.BaselineConstants.FIRST_FIXED_LOCAL_REGISTER;
- import static org.jikesrvm.ppc.BaselineConstants.FIRST_FLOAT_LOCAL_REGISTER;
- import static org.jikesrvm.ppc.RegisterConstants.FIRST_VOLATILE_FPR;
- import static org.jikesrvm.ppc.RegisterConstants.FIRST_VOLATILE_GPR;
- import static org.jikesrvm.ppc.RegisterConstants.LAST_NONVOLATILE_FPR;
- import static org.jikesrvm.ppc.RegisterConstants.LAST_NONVOLATILE_GPR;
- import static org.jikesrvm.runtime.JavaSizeConstants.BYTES_IN_DOUBLE;
- import static org.jikesrvm.runtime.JavaSizeConstants.LOG_BYTES_IN_DOUBLE;
- import static org.jikesrvm.runtime.UnboxedSizeConstants.BYTES_IN_ADDRESS;
- import org.jikesrvm.VM;
- import org.jikesrvm.classloader.NormalMethod;
- import org.jikesrvm.compilers.baseline.AbstractBaselineGCMapIterator;
- import org.jikesrvm.compilers.common.CompiledMethod;
- import org.jikesrvm.runtime.Magic;
- import org.vmmagic.pragma.Uninterruptible;
- import org.vmmagic.unboxed.Address;
- import org.vmmagic.unboxed.AddressArray;
- import org.vmmagic.unboxed.Offset;
- /**
- * Iterator for stack frame built by the Baseline compiler.<p>
- *
- * An Instance of this class will iterate through a particular
- * reference map of a method returning the offsets of any references
- * that are part of the input parameters, local variables, and
- * java stack for the stack frame.
- */
- @Uninterruptible
- public final class BaselineGCMapIterator extends AbstractBaselineGCMapIterator {
- /** Compiled method for the frame */
- protected ArchBaselineCompiledMethod currentCompiledMethod;
- public BaselineGCMapIterator(AddressArray registerLocations) {
- super(registerLocations);
- bridgeData = new ArchBridgeDataExtractor();
- }
- /**
- * Set the iterator to scan the map at the machine instruction offset
- * provided. The iterator is positioned to the beginning of the map. NOTE: An
- * iterator may be reused to scan a different method and map.
- *
- * @param compiledMethod
- * identifies the method and class
- * @param instructionOffset
- * identifies the map to be scanned.
- * @param fp
- * identifies a specific occurrance of this method and allows for
- * processing instance specific information i.e JSR return address
- * values
- */
- @Override
- public void setupIterator(CompiledMethod compiledMethod, Offset instructionOffset, Address fp) {
- currentCompiledMethod = (ArchBaselineCompiledMethod) compiledMethod;
- currentMethod = (NormalMethod) compiledMethod.getMethod();
- currentNumLocals = currentMethod.getLocalWords();
- // setup superclass
- //
- framePtr = fp;
- // setup stackframe mapping
- //
- mapReader.setMethod(currentMethod, compiledMethod);
- mapReader.locateGCPoint(instructionOffset);
- if (mapReader.currentMapIsForJSR()) {
- mapReader.acquireLockForJSRProcessing();
- int JSRindex = mapReader.setupJSRSubroutineMap();
- while (JSRindex != 0) {
- Address nextCallerAddress;
- short location = convertIndexToLocation(JSRindex);
- if (BaselineCompilerImpl.isRegister(location)) {
- nextCallerAddress = registerLocations.get(location);
- } else {
- nextCallerAddress =
- framePtr.plus(BaselineCompilerImpl.locationToOffset(location) -
- BYTES_IN_ADDRESS); //location offsets are positioned on top of stackslot
- }
- nextCallerAddress = nextCallerAddress.loadAddress();
- Offset nextMachineCodeOffset = compiledMethod.getInstructionOffset(nextCallerAddress);
- if (VM.TraceStkMaps) {
- traceSetupJSRsubroutineMap(JSRindex, nextCallerAddress, nextMachineCodeOffset);
- }
- JSRindex = mapReader.getNextJSRAddressIndex(nextMachineCodeOffset);
- }
- }
- if (VM.TraceStkMaps || TRACE_ALL) {
- VM.sysWrite("BaselineGCMapIterator setupIterator mapId = ");
- VM.sysWrite(mapReader.getMapId());
- VM.sysWrite(" for ");
- VM.sysWrite(currentMethod);
- VM.sysWriteln(".");
- }
- bridgeData.setupDynamicBridgeMapping(currentMethod, fp);
- reset();
- }
- @Override
- protected void resetArchitectureSpecificBridgeSState() {
- bridgeData.resetBridgeRegisterIndex();
- bridgeData.setBridgeRegisterLocation(framePtr.loadAddress());
- // point to first saved gpr
- bridgeData.decBrigeRegisterLocation(BYTES_IN_DOUBLE * (LAST_NONVOLATILE_FPR.value() - FIRST_VOLATILE_FPR.value() + 1) +
- BYTES_IN_ADDRESS * (LAST_NONVOLATILE_GPR.value() - FIRST_VOLATILE_GPR.value() + 1));
- // get to my caller's frameptr and then walk up to the spill area
- Address callersFP = Magic.getCallerFramePointer(framePtr);
- bridgeData.resetBridgeSpilledParamLocation(callersFP);
- }
- /**
- * given a index in the local area (biased : local0 has index 1)
- * this routine determines the correspondig offset in the stack
- */
- public short convertIndexToLocation(int index) {
- if (index == 0) return 0;
- if (index <= currentNumLocals) { //index is biased by 1;
- //register (positive value) or stacklocation (negative value)
- return currentCompiledMethod.getGeneralLocalLocation(index - 1);
- } else {
- //locations must point to the top of the slot
- return currentCompiledMethod.getGeneralStackLocation(index - 1 - currentNumLocals);
- }
- }
- @Override
- public Address getNextReferenceAddress() {
- if (!mapReader.isFinishedWithRegularMap()) {
- mapReader.updateMapIndex();
- if (VM.TraceStkMaps || TRACE_ALL) {
- VM.sysWrite("BaselineGCMapIterator getNextReferenceIndex = ");
- VM.sysWrite(mapReader.getMapIndex());
- VM.sysWriteln(".");
- if (mapReader.currentMapIsForJSR()) {
- VM.sysWriteln("Index is a JSR return address ie internal pointer.");
- }
- }
- if (mapReader.currentMapHasMorePointers()) {
- short location = convertIndexToLocation(mapReader.getMapIndex());
- if (VM.TraceStkMaps || TRACE_ALL) {
- VM.sysWrite("BaselineGCMapIterator getNextReference location = ");
- VM.sysWrite(location);
- VM.sysWriteln();
- }
- if (BaselineCompilerImpl.isRegister(location)) {
- return registerLocations.get(location);
- } else {
- return framePtr.plus(BaselineCompilerImpl.locationToOffset(location) -
- BYTES_IN_ADDRESS); //location offsets are positioned on top of stackslot
- }
- } else {
- // remember that we are done with the map for future calls, and then
- // drop down to the code below
- mapReader.setFinishedWithRegularMap();
- }
- }
- if (bridgeData.isBridgeParameterMappingRequired()) {
- if (bridgeData.needsBridgeRegisterLocationsUpdate()) {
- // point registerLocations[] to our callers stackframe
- //
- Address location = framePtr.plus(currentCompiledMethod.getFrameSize());
- location = location.minus((LAST_NONVOLATILE_FPR.value() - FIRST_VOLATILE_FPR.value() + 1) * BYTES_IN_DOUBLE);
- // skip non-volatile and volatile fprs
- for (int i = LAST_NONVOLATILE_GPR.value(); i >= FIRST_VOLATILE_GPR.value(); --i) {
- location = location.minus(BYTES_IN_ADDRESS);
- registerLocations.set(i, location);
- }
- bridgeData.setBridgeRegistersLocationUpdated();
- }
- if (bridgeData.hasUnprocessedImplicitThis()) {
- return bridgeData.getImplicitThisAddress();
- }
- // now the remaining parameters
- //
- while (bridgeData.hasMoreBridgeParameters()) {
- return bridgeData.getNextBridgeParameterAddress();
- }
- }
- return Address.zero();
- }
- @Override
- public Address getNextReturnAddressAddress() {
- if (!mapReader.currentMapIsForJSR()) {
- if (VM.TraceStkMaps || TRACE_ALL) {
- traceMapIdForGetNextReturnAddressAddress();
- }
- return Address.zero();
- }
- mapReader.updateMapIndexWithJSRReturnAddrIndex();
- if (VM.TraceStkMaps || TRACE_ALL) {
- VM.sysWrite("BaselineGCMapIterator getNextReturnAddressIndex = ");
- VM.sysWrite(mapReader.getMapIndex());
- VM.sysWriteln(".");
- }
- if (!mapReader.currentMapHasMorePointers()) return Address.zero();
- short location = convertIndexToLocation(mapReader.getMapIndex());
- if (VM.TraceStkMaps || TRACE_ALL) {
- VM.sysWrite("BaselineGCMapIterator getNextReturnAddress location = ");
- VM.sysWrite(location);
- VM.sysWriteln(".");
- }
- if (BaselineCompilerImpl.isRegister(location)) {
- return registerLocations.get(location);
- } else {
- return framePtr.plus(BaselineCompilerImpl.locationToOffset(location) -
- BYTES_IN_ADDRESS); //location offsets are positioned on top of stackslot
- }
- }
- @Override
- public void cleanupPointers() {
- // Make sure that the registerLocation array is updated with the
- // locations where this method cached its callers registers.
- // [[Yuck. I hate having to do this here, but it seems to be the
- // only safe way to do this...]]
- updateCallerRegisterLocations();
- super.cleanupPointers();
- }
- private void updateCallerRegisterLocations() {
- //dynamic bridge's registers already restored by calls to getNextReferenceAddress()
- if (!currentMethod.getDeclaringClass().hasDynamicBridgeAnnotation()) {
- if (VM.TraceStkMaps || TRACE_ALL) VM.sysWriteln(" Update Caller RegisterLocations");
- Address addr = framePtr.plus(currentCompiledMethod.getFrameSize());
- addr =
- addr.minus((currentCompiledMethod.getLastFloatStackRegister() - FIRST_FLOAT_LOCAL_REGISTER.value() + 1) <<
- LOG_BYTES_IN_DOUBLE); //skip float registers
- for (int i = currentCompiledMethod.getLastFixedStackRegister(); i >= FIRST_FIXED_LOCAL_REGISTER.value(); --i) {
- addr = addr.minus(BYTES_IN_ADDRESS);
- registerLocations.set(i, addr);
- }
- }
- }
- }