| /* |
| * 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); |
| } |
| } |
| } |