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.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( 147 ~((debugValue << config.deoptimizationDebugIdShift) | (reasonValue << config.deoptimizationReasonShift) | (actionValue << config.deoptimizationActionShift))); 148 assert c.asInt() < 0; 149 return c; 150 } 151 152 public DeoptimizationReason decodeDeoptReason(JavaConstant constant) { 153 HotSpotVMConfig config = runtime.getConfig(); 154 int reasonValue = ((~constant.asInt()) >> config.deoptimizationReasonShift) & intMaskRight(config.deoptimizationReasonBits); 155 DeoptimizationReason reason = convertDeoptReason(reasonValue); 156 return reason; 157 } 158 159 public DeoptimizationAction decodeDeoptAction(JavaConstant constant) { 160 HotSpotVMConfig config = runtime.getConfig(); 161 int actionValue = ((~constant.asInt()) >> config.deoptimizationActionShift) & intMaskRight(config.deoptimizationActionBits); 162 DeoptimizationAction action = convertDeoptAction(actionValue); 163 return action; 164 } 165 166 public int decodeDebugId(JavaConstant constant) { 167 HotSpotVMConfig config = runtime.getConfig(); 168 return ((~constant.asInt()) >> config.deoptimizationDebugIdShift) & intMaskRight(config.deoptimizationDebugIdBits); 169 } 170 171 public int convertDeoptAction(DeoptimizationAction action) { 172 HotSpotVMConfig config = runtime.getConfig(); 173 switch (action) { 174 case None: 175 return config.deoptActionNone; 176 case RecompileIfTooManyDeopts: 177 return config.deoptActionMaybeRecompile; 178 case InvalidateReprofile: 179 return config.deoptActionReinterpret; 180 case InvalidateRecompile: 181 return config.deoptActionMakeNotEntrant; 182 case InvalidateStopCompiling: 183 return config.deoptActionMakeNotCompilable; 184 default: 185 throw new JVMCIError("%s", action); 186 } 187 } 188 189 public DeoptimizationAction convertDeoptAction(int action) { 190 HotSpotVMConfig config = runtime.getConfig(); 191 if (action == config.deoptActionNone) { 192 return DeoptimizationAction.None; 193 } 194 if (action == config.deoptActionMaybeRecompile) { 195 return DeoptimizationAction.RecompileIfTooManyDeopts; 196 } 197 if (action == config.deoptActionReinterpret) { 198 return DeoptimizationAction.InvalidateReprofile; 199 } 200 if (action == config.deoptActionMakeNotEntrant) { 201 return DeoptimizationAction.InvalidateRecompile; 202 } 203 if (action == config.deoptActionMakeNotCompilable) { 204 return DeoptimizationAction.InvalidateStopCompiling; 205 } 206 throw new JVMCIError("%d", action); 207 } 208 209 public int convertDeoptReason(DeoptimizationReason reason) { 210 HotSpotVMConfig config = runtime.getConfig(); 211 switch (reason) { 212 case None: 213 return config.deoptReasonNone; 214 case NullCheckException: 215 return config.deoptReasonNullCheck; 216 case BoundsCheckException: 217 return config.deoptReasonRangeCheck; 218 case ClassCastException: 219 return config.deoptReasonClassCheck; 220 case ArrayStoreException: 221 return config.deoptReasonArrayCheck; 222 case UnreachedCode: 223 return config.deoptReasonUnreached0; 224 case TypeCheckedInliningViolated: 225 return config.deoptReasonTypeCheckInlining; 226 case OptimizedTypeCheckViolated: 227 return config.deoptReasonOptimizedTypeCheck; 228 case NotCompiledExceptionHandler: 229 return config.deoptReasonNotCompiledExceptionHandler; 230 case Unresolved: 231 return config.deoptReasonUnresolved; 232 case JavaSubroutineMismatch: 233 return config.deoptReasonJsrMismatch; 234 case ArithmeticException: 235 return config.deoptReasonDiv0Check; 236 case RuntimeConstraint: 237 return config.deoptReasonConstraint; 238 case LoopLimitCheck: 239 return config.deoptReasonLoopLimitCheck; 240 case Aliasing: 241 return config.deoptReasonAliasing; 242 case TransferToInterpreter: 243 return config.deoptReasonTransferToInterpreter; 244 default: 245 throw new JVMCIError("%s", reason); 246 } 247 } 248 249 public DeoptimizationReason convertDeoptReason(int reason) { 250 HotSpotVMConfig config = runtime.getConfig(); 251 if (reason == config.deoptReasonNone) { 252 return DeoptimizationReason.None; 253 } 254 if (reason == config.deoptReasonNullCheck) { 255 return DeoptimizationReason.NullCheckException; 256 } 257 if (reason == config.deoptReasonRangeCheck) { 258 return DeoptimizationReason.BoundsCheckException; 259 } 260 if (reason == config.deoptReasonClassCheck) { 261 return DeoptimizationReason.ClassCastException; 262 } 263 if (reason == config.deoptReasonArrayCheck) { 264 return DeoptimizationReason.ArrayStoreException; 265 } 266 if (reason == config.deoptReasonUnreached0) { 267 return DeoptimizationReason.UnreachedCode; 268 } 269 if (reason == config.deoptReasonTypeCheckInlining) { 270 return DeoptimizationReason.TypeCheckedInliningViolated; 271 } 272 if (reason == config.deoptReasonOptimizedTypeCheck) { 273 return DeoptimizationReason.OptimizedTypeCheckViolated; 274 } 275 if (reason == config.deoptReasonNotCompiledExceptionHandler) { 276 return DeoptimizationReason.NotCompiledExceptionHandler; 277 } 278 if (reason == config.deoptReasonUnresolved) { 279 return DeoptimizationReason.Unresolved; 280 } 281 if (reason == config.deoptReasonJsrMismatch) { 282 return DeoptimizationReason.JavaSubroutineMismatch; 283 } 284 if (reason == config.deoptReasonDiv0Check) { 285 return DeoptimizationReason.ArithmeticException; 286 } 287 if (reason == config.deoptReasonConstraint) { 288 return DeoptimizationReason.RuntimeConstraint; 289 } 290 if (reason == config.deoptReasonLoopLimitCheck) { 291 return DeoptimizationReason.LoopLimitCheck; 292 } 293 if (reason == config.deoptReasonAliasing) { 294 return DeoptimizationReason.Aliasing; 295 } 296 if (reason == config.deoptReasonTransferToInterpreter) { 297 return DeoptimizationReason.TransferToInterpreter; 298 } 299 throw new JVMCIError("%x", reason); 300 } 301 302 @Override 303 public long getMemorySize(JavaConstant constant) { 304 if (constant.getJavaKind() == JavaKind.Object) { 305 HotSpotResolvedObjectType lookupJavaType = lookupJavaType(constant); 306 307 if (lookupJavaType == null) { 308 return 0; 309 } else { 310 if (lookupJavaType.isArray()) { 311 // TODO(tw): Add compressed pointer support. 312 int length = Array.getLength(((HotSpotObjectConstantImpl) constant).object()); 313 ResolvedJavaType elementType = lookupJavaType.getComponentType(); 314 JavaKind elementKind = elementType.getJavaKind(); 315 final int headerSize = getArrayBaseOffset(elementKind); 316 TargetDescription target = runtime.getHostJVMCIBackend().getTarget(); 317 int sizeOfElement = getArrayIndexScale(elementKind); 318 int alignment = target.wordSize; 319 int log2ElementSize = CodeUtil.log2(sizeOfElement); 320 return computeArrayAllocationSize(length, alignment, headerSize, log2ElementSize); 321 } 322 return lookupJavaType.instanceSize(); 323 } 324 } else { 325 return constant.getJavaKind().getByteCount(); 326 } 327 } 328 329 /** 330 * Computes the size of the memory chunk allocated for an array. This size accounts for the 331 * array header size, body size and any padding after the last element to satisfy object 332 * alignment requirements. 333 * 334 * @param length the number of elements in the array 335 * @param alignment the object alignment requirement 336 * @param headerSize the size of the array header 337 * @param log2ElementSize log2 of the size of an element in the array 338 */ 339 public static int computeArrayAllocationSize(int length, int alignment, int headerSize, int log2ElementSize) { 340 int size = (length << log2ElementSize) + headerSize + (alignment - 1); 341 int mask = ~(alignment - 1); 342 return size & mask; 343 } 344 }