blob: a8b7982ebf467a3628ad3dc6f3fb8487ff85829d [file] [log] [blame]
/*
* Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.graalvm.compiler.hotspot;
import static org.graalvm.compiler.lir.LIRValueUtil.isJavaConstant;
import static jdk.vm.ci.code.ValueUtil.asRegister;
import static jdk.vm.ci.code.ValueUtil.asStackSlot;
import static jdk.vm.ci.code.ValueUtil.isRegister;
import java.util.ArrayList;
import org.graalvm.compiler.common.PermanentBailoutException;
import org.graalvm.compiler.core.common.LIRKind;
import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.lir.LIRFrameState;
import org.graalvm.compiler.lir.Variable;
import org.graalvm.compiler.lir.framemap.ReferenceMapBuilder;
import jdk.vm.ci.code.Location;
import jdk.vm.ci.code.ReferenceMap;
import jdk.vm.ci.code.StackSlot;
import jdk.vm.ci.hotspot.HotSpotReferenceMap;
import jdk.vm.ci.meta.PlatformKind;
import jdk.vm.ci.meta.Value;
public final class HotSpotReferenceMapBuilder extends ReferenceMapBuilder {
private int maxRegisterSize;
private final ArrayList<Value> objectValues;
private int objectCount;
private final int totalFrameSize;
private final int maxOopMapStackOffset;
public HotSpotReferenceMapBuilder(int totalFrameSize, int maxOopMapStackOffset) {
this.objectValues = new ArrayList<>();
this.objectCount = 0;
this.maxOopMapStackOffset = maxOopMapStackOffset;
this.totalFrameSize = totalFrameSize;
}
@Override
public void addLiveValue(Value v) {
if (isJavaConstant(v)) {
return;
}
LIRKind lirKind = (LIRKind) v.getValueKind();
if (!lirKind.isValue()) {
objectValues.add(v);
if (lirKind.isUnknownReference()) {
objectCount++;
} else {
objectCount += lirKind.getReferenceCount();
}
}
if (isRegister(v)) {
int size = lirKind.getPlatformKind().getSizeInBytes();
if (size > maxRegisterSize) {
maxRegisterSize = size;
}
}
}
private static final Location[] NO_LOCATIONS = {};
private static final int[] NO_SIZES = {};
@Override
public ReferenceMap finish(LIRFrameState state) {
Location[] objects;
Location[] derivedBase;
int[] sizeInBytes;
if (objectCount == 0) {
objects = NO_LOCATIONS;
derivedBase = NO_LOCATIONS;
sizeInBytes = NO_SIZES;
} else {
objects = new Location[objectCount];
derivedBase = new Location[objectCount];
sizeInBytes = new int[objectCount];
}
int idx = 0;
for (Value obj : objectValues) {
LIRKind kind = (LIRKind) obj.getValueKind();
int bytes = bytesPerElement(kind);
if (kind.isUnknownReference()) {
throw GraalError.shouldNotReachHere("unknown reference alive across safepoint");
} else {
Location base = null;
if (kind.isDerivedReference()) {
Variable baseVariable = (Variable) kind.getDerivedReferenceBase();
Value baseValue = state.getLiveBasePointers().get(baseVariable.index);
assert baseValue.getPlatformKind().getVectorLength() == 1 && ((LIRKind) baseValue.getValueKind()).isReference(0) && !((LIRKind) baseValue.getValueKind()).isDerivedReference();
base = toLocation(baseValue, 0);
}
for (int i = 0; i < kind.getPlatformKind().getVectorLength(); i++) {
if (kind.isReference(i)) {
objects[idx] = toLocation(obj, i * bytes);
derivedBase[idx] = base;
sizeInBytes[idx] = bytes;
idx++;
}
}
}
}
return new HotSpotReferenceMap(objects, derivedBase, sizeInBytes, maxRegisterSize);
}
private static int bytesPerElement(LIRKind kind) {
PlatformKind platformKind = kind.getPlatformKind();
return platformKind.getSizeInBytes() / platformKind.getVectorLength();
}
private Location toLocation(Value v, int offset) {
if (isRegister(v)) {
return Location.subregister(asRegister(v), offset);
} else {
StackSlot s = asStackSlot(v);
int totalOffset = s.getOffset(totalFrameSize) + offset;
if (totalOffset > maxOopMapStackOffset) {
throw new PermanentBailoutException("stack offset %d for oopmap is greater than encoding limit %d", totalOffset, maxOopMapStackOffset);
}
return Location.stack(totalOffset);
}
}
}