1 /* 2 * Copyright (c) 2011, 2016, 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 jdk.vm.ci.hotspot; 24 25 import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayBaseOffset; 26 import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayIndexScale; 27 import static jdk.vm.ci.hotspot.HotSpotResolvedObjectTypeImpl.fromObjectClass; 28 import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE; 29 30 import java.lang.reflect.Array; 31 import java.lang.reflect.Executable; 32 import java.lang.reflect.Field; 33 import java.lang.reflect.Modifier; 34 import java.util.Objects; 35 36 import jdk.vm.ci.code.CodeUtil; 37 import jdk.vm.ci.common.JVMCIError; 38 import jdk.vm.ci.meta.DeoptimizationAction; 39 import jdk.vm.ci.meta.DeoptimizationReason; 40 import jdk.vm.ci.meta.JavaConstant; 41 import jdk.vm.ci.meta.JavaKind; 42 import jdk.vm.ci.meta.MetaAccessProvider; 43 import jdk.vm.ci.meta.ResolvedJavaField; 44 import jdk.vm.ci.meta.ResolvedJavaMethod; 45 import jdk.vm.ci.meta.ResolvedJavaType; 46 import jdk.vm.ci.meta.Signature; 47 48 // JaCoCo Exclude 49 50 /** 51 * HotSpot implementation of {@link MetaAccessProvider}. 52 */ 53 public class HotSpotMetaAccessProvider implements MetaAccessProvider { 54 55 protected final HotSpotJVMCIRuntimeProvider runtime; 56 57 public HotSpotMetaAccessProvider(HotSpotJVMCIRuntimeProvider runtime) { 58 this.runtime = runtime; 59 } 60 61 public ResolvedJavaType lookupJavaType(Class<?> clazz) { 62 if (clazz == null) { 63 throw new IllegalArgumentException("Class parameter was null"); 64 } 65 return runtime.fromClass(clazz); 66 } 67 68 public HotSpotResolvedObjectType lookupJavaType(JavaConstant constant) { 69 if (constant.isNull() || !(constant instanceof HotSpotObjectConstant)) { 70 return null; 71 } 72 return ((HotSpotObjectConstant) constant).getType(); 73 } 74 75 public Signature parseMethodDescriptor(String signature) { 76 return new HotSpotSignature(runtime, signature); 77 } 78 79 public ResolvedJavaMethod lookupJavaMethod(Executable reflectionMethod) { 80 return runtime.getCompilerToVM().asResolvedJavaMethod(Objects.requireNonNull(reflectionMethod)); 81 } 82 83 public ResolvedJavaField lookupJavaField(Field reflectionField) { 84 Class<?> fieldHolder = reflectionField.getDeclaringClass(); 85 86 HotSpotResolvedObjectType holder = fromObjectClass(fieldHolder); 87 if (Modifier.isStatic(reflectionField.getModifiers())) { 88 final long offset = UNSAFE.staticFieldOffset(reflectionField); 89 for (ResolvedJavaField field : holder.getStaticFields()) { 90 if (offset == ((HotSpotResolvedJavaField) field).offset()) { 91 return field; 92 } 93 } 94 } else { 95 final long offset = UNSAFE.objectFieldOffset(reflectionField); 96 for (ResolvedJavaField field : holder.getInstanceFields(false)) { 97 if (offset == ((HotSpotResolvedJavaField) field).offset()) { 98 return field; 99 } 100 } 101 } 102 103 throw new JVMCIError("unresolved field %s", reflectionField); 104 } 105 106 private static int intMaskRight(int n) { 107 assert n <= 32; 108 return n == 32 ? -1 : (1 << n) - 1; 109 } 110 111 @Override 112 public JavaConstant encodeDeoptActionAndReason(DeoptimizationAction action, DeoptimizationReason reason, int debugId) { 113 HotSpotVMConfig config = runtime.getConfig(); 114 int actionValue = convertDeoptAction(action); 115 int reasonValue = convertDeoptReason(reason); 116 int debugValue = debugId & intMaskRight(config.deoptimizationDebugIdBits); 117 JavaConstant c = JavaConstant.forInt( 118 ~((debugValue << config.deoptimizationDebugIdShift) | (reasonValue << config.deoptimizationReasonShift) | (actionValue << config.deoptimizationActionShift))); 119 assert c.asInt() < 0; 120 return c; 121 } 122 123 public DeoptimizationReason decodeDeoptReason(JavaConstant constant) { 124 HotSpotVMConfig config = runtime.getConfig(); 125 int reasonValue = ((~constant.asInt()) >> config.deoptimizationReasonShift) & intMaskRight(config.deoptimizationReasonBits); 126 DeoptimizationReason reason = convertDeoptReason(reasonValue); 127 return reason; 128 } 129 130 public DeoptimizationAction decodeDeoptAction(JavaConstant constant) { 131 HotSpotVMConfig config = runtime.getConfig(); 132 int actionValue = ((~constant.asInt()) >> config.deoptimizationActionShift) & intMaskRight(config.deoptimizationActionBits); 133 DeoptimizationAction action = convertDeoptAction(actionValue); 134 return action; 135 } 136 137 public int decodeDebugId(JavaConstant constant) { 138 HotSpotVMConfig config = runtime.getConfig(); 139 return ((~constant.asInt()) >> config.deoptimizationDebugIdShift) & intMaskRight(config.deoptimizationDebugIdBits); 140 } 141 142 public int convertDeoptAction(DeoptimizationAction action) { 143 HotSpotVMConfig config = runtime.getConfig(); 144 switch (action) { 145 case None: 146 return config.deoptActionNone; 147 case RecompileIfTooManyDeopts: 148 return config.deoptActionMaybeRecompile; 149 case InvalidateReprofile: 150 return config.deoptActionReinterpret; 151 case InvalidateRecompile: 152 return config.deoptActionMakeNotEntrant; 153 case InvalidateStopCompiling: 154 return config.deoptActionMakeNotCompilable; 155 default: 156 throw new JVMCIError("%s", action); 157 } 158 } 159 160 public DeoptimizationAction convertDeoptAction(int action) { 161 HotSpotVMConfig config = runtime.getConfig(); 162 if (action == config.deoptActionNone) { 163 return DeoptimizationAction.None; 164 } 165 if (action == config.deoptActionMaybeRecompile) { 166 return DeoptimizationAction.RecompileIfTooManyDeopts; 167 } 168 if (action == config.deoptActionReinterpret) { 169 return DeoptimizationAction.InvalidateReprofile; 170 } 171 if (action == config.deoptActionMakeNotEntrant) { 172 return DeoptimizationAction.InvalidateRecompile; 173 } 174 if (action == config.deoptActionMakeNotCompilable) { 175 return DeoptimizationAction.InvalidateStopCompiling; 176 } 177 throw new JVMCIError("%d", action); 178 } 179 180 public int convertDeoptReason(DeoptimizationReason reason) { 181 HotSpotVMConfig config = runtime.getConfig(); 182 switch (reason) { 183 case None: 184 return config.deoptReasonNone; 185 case NullCheckException: 186 return config.deoptReasonNullCheck; 187 case BoundsCheckException: 188 return config.deoptReasonRangeCheck; 189 case ClassCastException: 190 return config.deoptReasonClassCheck; 191 case ArrayStoreException: 192 return config.deoptReasonArrayCheck; 193 case UnreachedCode: 194 return config.deoptReasonUnreached0; 195 case TypeCheckedInliningViolated: 196 return config.deoptReasonTypeCheckInlining; 197 case OptimizedTypeCheckViolated: 198 return config.deoptReasonOptimizedTypeCheck; 199 case NotCompiledExceptionHandler: 200 return config.deoptReasonNotCompiledExceptionHandler; 201 case Unresolved: 202 return config.deoptReasonUnresolved; 203 case JavaSubroutineMismatch: 204 return config.deoptReasonJsrMismatch; 205 case ArithmeticException: 206 return config.deoptReasonDiv0Check; 207 case RuntimeConstraint: 208 return config.deoptReasonConstraint; 209 case LoopLimitCheck: 210 return config.deoptReasonLoopLimitCheck; 211 case Aliasing: 212 return config.deoptReasonAliasing; 213 case TransferToInterpreter: 214 return config.deoptReasonTransferToInterpreter; 215 default: 216 throw new JVMCIError("%s", reason); 217 } 218 } 219 220 public DeoptimizationReason convertDeoptReason(int reason) { 221 HotSpotVMConfig config = runtime.getConfig(); 222 if (reason == config.deoptReasonNone) { 223 return DeoptimizationReason.None; 224 } 225 if (reason == config.deoptReasonNullCheck) { 226 return DeoptimizationReason.NullCheckException; 227 } 228 if (reason == config.deoptReasonRangeCheck) { 229 return DeoptimizationReason.BoundsCheckException; 230 } 231 if (reason == config.deoptReasonClassCheck) { 232 return DeoptimizationReason.ClassCastException; 233 } 234 if (reason == config.deoptReasonArrayCheck) { 235 return DeoptimizationReason.ArrayStoreException; 236 } 237 if (reason == config.deoptReasonUnreached0) { 238 return DeoptimizationReason.UnreachedCode; 239 } 240 if (reason == config.deoptReasonTypeCheckInlining) { 241 return DeoptimizationReason.TypeCheckedInliningViolated; 242 } 243 if (reason == config.deoptReasonOptimizedTypeCheck) { 244 return DeoptimizationReason.OptimizedTypeCheckViolated; 245 } 246 if (reason == config.deoptReasonNotCompiledExceptionHandler) { 247 return DeoptimizationReason.NotCompiledExceptionHandler; 248 } 249 if (reason == config.deoptReasonUnresolved) { 250 return DeoptimizationReason.Unresolved; 251 } 252 if (reason == config.deoptReasonJsrMismatch) { 253 return DeoptimizationReason.JavaSubroutineMismatch; 254 } 255 if (reason == config.deoptReasonDiv0Check) { 256 return DeoptimizationReason.ArithmeticException; 257 } 258 if (reason == config.deoptReasonConstraint) { 259 return DeoptimizationReason.RuntimeConstraint; 260 } 261 if (reason == config.deoptReasonLoopLimitCheck) { 262 return DeoptimizationReason.LoopLimitCheck; 263 } 264 if (reason == config.deoptReasonAliasing) { 265 return DeoptimizationReason.Aliasing; 266 } 267 if (reason == config.deoptReasonTransferToInterpreter) { 268 return DeoptimizationReason.TransferToInterpreter; 269 } 270 throw new JVMCIError("%x", reason); 271 } 272 273 @Override 274 public long getMemorySize(JavaConstant constant) { 275 if (constant.getJavaKind() == JavaKind.Object) { 276 HotSpotResolvedObjectType lookupJavaType = lookupJavaType(constant); 277 278 if (lookupJavaType == null) { 279 return 0; 280 } else { 281 if (lookupJavaType.isArray()) { 282 int length = Array.getLength(((HotSpotObjectConstantImpl) constant).object()); 283 ResolvedJavaType elementType = lookupJavaType.getComponentType(); 284 JavaKind elementKind = elementType.getJavaKind(); 285 final int headerSize = getArrayBaseOffset(elementKind); 286 int sizeOfElement = getArrayIndexScale(elementKind); 287 int log2ElementSize = CodeUtil.log2(sizeOfElement); 288 return computeArrayAllocationSize(length, headerSize, log2ElementSize); 289 } 290 return lookupJavaType.instanceSize(); 291 } 292 } else { 293 return constant.getJavaKind().getByteCount(); 294 } 295 } 296 297 /** 298 * Computes the size of the memory chunk allocated for an array. This size accounts for the 299 * array header size, body size and any padding after the last element to satisfy object 300 * alignment requirements. 301 * 302 * @param length the number of elements in the array 303 * @param headerSize the size of the array header 304 * @param log2ElementSize log2 of the size of an element in the array 305 * @return the size of the memory chunk 306 */ 307 public int computeArrayAllocationSize(int length, int headerSize, int log2ElementSize) { 308 HotSpotVMConfig config = runtime.getConfig(); 309 int alignment = config.objectAlignment; 310 int size = (length << log2ElementSize) + headerSize + (alignment - 1); 311 int mask = ~(alignment - 1); 312 return size & mask; 313 } 314 }