1 /* 2 * Copyright (c) 2009, 2018, 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 24 25 package org.graalvm.compiler.hotspot; 26 27 import static jdk.vm.ci.code.ValueUtil.asRegister; 28 import static jdk.vm.ci.code.ValueUtil.asStackSlot; 29 import static jdk.vm.ci.code.ValueUtil.isRegister; 30 import static org.graalvm.compiler.lir.LIRValueUtil.isJavaConstant; 31 32 import java.util.ArrayList; 33 34 import org.graalvm.compiler.core.common.LIRKind; 35 import org.graalvm.compiler.core.common.PermanentBailoutException; 36 import org.graalvm.compiler.debug.GraalError; 37 import org.graalvm.compiler.lir.LIRFrameState; 38 import org.graalvm.compiler.lir.Variable; 39 import org.graalvm.compiler.lir.framemap.ReferenceMapBuilder; 40 41 import jdk.vm.ci.code.Location; 42 import jdk.vm.ci.code.ReferenceMap; 43 import jdk.vm.ci.code.StackSlot; 44 import jdk.vm.ci.hotspot.HotSpotReferenceMap; 45 import jdk.vm.ci.meta.PlatformKind; 46 import jdk.vm.ci.meta.Value; 47 48 public final class HotSpotReferenceMapBuilder extends ReferenceMapBuilder { 49 50 private int maxRegisterSize; 51 52 private final ArrayList<Value> objectValues; 53 private int objectCount; 54 55 private final int totalFrameSize; 56 private final int maxOopMapStackOffset; 57 private final int uncompressedReferenceSize; 58 HotSpotReferenceMapBuilder(int totalFrameSize, int maxOopMapStackOffset, int uncompressedReferenceSize)59 public HotSpotReferenceMapBuilder(int totalFrameSize, int maxOopMapStackOffset, int uncompressedReferenceSize) { 60 this.uncompressedReferenceSize = uncompressedReferenceSize; 61 this.objectValues = new ArrayList<>(); 62 this.objectCount = 0; 63 this.maxOopMapStackOffset = maxOopMapStackOffset; 64 this.totalFrameSize = totalFrameSize; 65 } 66 67 @Override addLiveValue(Value v)68 public void addLiveValue(Value v) { 69 if (isJavaConstant(v)) { 70 return; 71 } 72 LIRKind lirKind = (LIRKind) v.getValueKind(); 73 if (!lirKind.isValue()) { 74 objectValues.add(v); 75 if (lirKind.isUnknownReference()) { 76 objectCount++; 77 } else { 78 objectCount += lirKind.getReferenceCount(); 79 } 80 } 81 if (isRegister(v)) { 82 int size = lirKind.getPlatformKind().getSizeInBytes(); 83 if (size > maxRegisterSize) { 84 maxRegisterSize = size; 85 } 86 } 87 } 88 89 private static final Location[] NO_LOCATIONS = {}; 90 private static final int[] NO_SIZES = {}; 91 92 @Override finish(LIRFrameState state)93 public ReferenceMap finish(LIRFrameState state) { 94 Location[] objects; 95 Location[] derivedBase; 96 int[] sizeInBytes; 97 if (objectCount == 0) { 98 objects = NO_LOCATIONS; 99 derivedBase = NO_LOCATIONS; 100 sizeInBytes = NO_SIZES; 101 } else { 102 objects = new Location[objectCount]; 103 derivedBase = new Location[objectCount]; 104 sizeInBytes = new int[objectCount]; 105 } 106 int idx = 0; 107 for (Value obj : objectValues) { 108 LIRKind kind = (LIRKind) obj.getValueKind(); 109 int bytes = bytesPerElement(kind); 110 if (kind.isUnknownReference()) { 111 throw GraalError.shouldNotReachHere(String.format("unknown reference alive across safepoint: %s", obj)); 112 } else { 113 Location base = null; 114 if (kind.isDerivedReference()) { 115 Variable baseVariable = (Variable) kind.getDerivedReferenceBase(); 116 Value baseValue = state.getLiveBasePointers().get(baseVariable.index); 117 assert baseValue.getPlatformKind().getVectorLength() == 1 && ((LIRKind) baseValue.getValueKind()).isReference(0) && !((LIRKind) baseValue.getValueKind()).isDerivedReference(); 118 base = toLocation(baseValue, 0); 119 } 120 121 for (int i = 0; i < kind.getPlatformKind().getVectorLength(); i++) { 122 if (kind.isReference(i)) { 123 assert kind.isCompressedReference(i) ? (bytes < uncompressedReferenceSize) : (bytes == uncompressedReferenceSize); 124 objects[idx] = toLocation(obj, i * bytes); 125 derivedBase[idx] = base; 126 sizeInBytes[idx] = bytes; 127 idx++; 128 } 129 } 130 } 131 } 132 133 return new HotSpotReferenceMap(objects, derivedBase, sizeInBytes, maxRegisterSize); 134 } 135 136 private static int bytesPerElement(LIRKind kind) { 137 PlatformKind platformKind = kind.getPlatformKind(); 138 return platformKind.getSizeInBytes() / platformKind.getVectorLength(); 139 } 140 141 private Location toLocation(Value v, int offset) { 142 if (isRegister(v)) { 143 return Location.subregister(asRegister(v), offset); 144 } else { 145 StackSlot s = asStackSlot(v); 146 int totalOffset = s.getOffset(totalFrameSize) + offset; 147 if (totalOffset > maxOopMapStackOffset) { 148 throw new PermanentBailoutException("stack offset %d for oopmap is greater than encoding limit %d", totalOffset, maxOopMapStackOffset); 149 } 150 return Location.stack(totalOffset); 151 } 152 } 153 } 154