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