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