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