1 /* 2 * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 package org.graalvm.compiler.hotspot; 24 25 import static jdk.vm.ci.code.ValueUtil.asRegister; 26 import static jdk.vm.ci.code.ValueUtil.asStackSlot; 27 import static jdk.vm.ci.code.ValueUtil.isRegister; 28 import static org.graalvm.compiler.lir.LIRValueUtil.isJavaConstant; 29 30 import java.util.ArrayList; 31 32 import org.graalvm.compiler.core.common.LIRKind; 33 import org.graalvm.compiler.core.common.PermanentBailoutException; 34 import org.graalvm.compiler.debug.GraalError; 35 import org.graalvm.compiler.lir.LIRFrameState; 36 import org.graalvm.compiler.lir.Variable; 37 import org.graalvm.compiler.lir.framemap.ReferenceMapBuilder; 38 39 import jdk.vm.ci.code.Location; 40 import jdk.vm.ci.code.ReferenceMap; 41 import jdk.vm.ci.code.StackSlot; 42 import jdk.vm.ci.hotspot.HotSpotReferenceMap; 43 import jdk.vm.ci.meta.PlatformKind; 44 import jdk.vm.ci.meta.Value; 45 46 public final class HotSpotReferenceMapBuilder extends ReferenceMapBuilder { 47 48 private int maxRegisterSize; 49 50 private final ArrayList<Value> objectValues; 51 private int objectCount; 52 53 private final int totalFrameSize; 54 private final int maxOopMapStackOffset; 55 private final int uncompressedReferenceSize; 56 57 public HotSpotReferenceMapBuilder(int totalFrameSize, int maxOopMapStackOffset, int uncompressedReferenceSize) { 58 this.uncompressedReferenceSize = uncompressedReferenceSize; 59 this.objectValues = new ArrayList<>(); 60 this.objectCount = 0; 61 this.maxOopMapStackOffset = maxOopMapStackOffset; 62 this.totalFrameSize = totalFrameSize; 63 } 64 65 @Override 66 public void addLiveValue(Value v) { 67 if (isJavaConstant(v)) { 68 return; 69 } 70 LIRKind lirKind = (LIRKind) v.getValueKind(); 71 if (!lirKind.isValue()) { 72 objectValues.add(v); 73 if (lirKind.isUnknownReference()) { 74 objectCount++; 75 } else { 76 objectCount += lirKind.getReferenceCount(); 77 } 78 } 79 if (isRegister(v)) { 80 int size = lirKind.getPlatformKind().getSizeInBytes(); 81 if (size > maxRegisterSize) { 82 maxRegisterSize = size; 83 } 84 } 85 } 86 87 private static final Location[] NO_LOCATIONS = {}; 88 private static final int[] NO_SIZES = {}; 89 90 @Override 91 public ReferenceMap finish(LIRFrameState state) { 92 Location[] objects; 93 Location[] derivedBase; 94 int[] sizeInBytes; 95 if (objectCount == 0) { 96 objects = NO_LOCATIONS; 97 derivedBase = NO_LOCATIONS; 98 sizeInBytes = NO_SIZES; 99 } else { 100 objects = new Location[objectCount]; 101 derivedBase = new Location[objectCount]; 102 sizeInBytes = new int[objectCount]; 103 } 104 int idx = 0; 105 for (Value obj : objectValues) { 106 LIRKind kind = (LIRKind) obj.getValueKind(); 107 int bytes = bytesPerElement(kind); 108 if (kind.isUnknownReference()) { 109 throw GraalError.shouldNotReachHere(String.format("unknown reference alive across safepoint: %s", obj)); 110 } else { 111 Location base = null; 112 if (kind.isDerivedReference()) { 113 Variable baseVariable = (Variable) kind.getDerivedReferenceBase(); 114 Value baseValue = state.getLiveBasePointers().get(baseVariable.index); 115 assert baseValue.getPlatformKind().getVectorLength() == 1 && ((LIRKind) baseValue.getValueKind()).isReference(0) && !((LIRKind) baseValue.getValueKind()).isDerivedReference(); 116 base = toLocation(baseValue, 0); 117 } 118 119 for (int i = 0; i < kind.getPlatformKind().getVectorLength(); i++) { 120 if (kind.isReference(i)) { 121 assert kind.isCompressedReference(i) ? (bytes < uncompressedReferenceSize) : (bytes == uncompressedReferenceSize); 122 objects[idx] = toLocation(obj, i * bytes); 123 derivedBase[idx] = base; 124 sizeInBytes[idx] = bytes; 125 idx++; 126 } 127 } 128 } 129 } 130 131 return new HotSpotReferenceMap(objects, derivedBase, sizeInBytes, maxRegisterSize); 132 } 133 134 private static int bytesPerElement(LIRKind kind) { 135 PlatformKind platformKind = kind.getPlatformKind(); 136 return platformKind.getSizeInBytes() / platformKind.getVectorLength(); 137 } 138 139 private Location toLocation(Value v, int offset) { 140 if (isRegister(v)) { 141 return Location.subregister(asRegister(v), offset); 142 } else { 143 StackSlot s = asStackSlot(v); 144 int totalOffset = s.getOffset(totalFrameSize) + offset; 145 if (totalOffset > maxOopMapStackOffset) { 146 throw new PermanentBailoutException("stack offset %d for oopmap is greater than encoding limit %d", totalOffset, maxOopMapStackOffset); 147 } 148 return Location.stack(totalOffset); 149 } 150 } 151 }